重学Node.js及其框架(Express, Koa, egg.js) 之 Nodejs基础(上)

简介: 重学Node.js及其框架(Express, Koa, egg.js) 之 Nodejs基础

总结自 Coderwhy的nodejs课程。


Express总结: juejin.cn/post/701653…


Koa总结:juejin.cn/post/701658…


nodejs官网:nodejs.org/dist/latest…


Nodejs是什么


Node.js是一个基于V8 JavaScript引擎的JavaScript运行时环境。


V8引擎原理


网络异常,图片无法展示
|


Parse模块会将JavaScript代码转换成AST(抽象语法树),这是因为解释器并不直接认识JavaScript代码;


  • 如果函数没有被调用,那么是不会被转换成AST的;


  • Parse的V8官方文档:v8.dev/blog/scanne…Ignition是一个解释器,会将AST转换成ByteCode(字节码)


  • 同时会收集TurboFan优化所需要的信息(比如函数参数的类型信息,有了类型才能进行真实的运算);


  • 如果函数只调用一次,Ignition会执行解释执行ByteCode;


  • Ignition的V8官方文档:v8.dev/blog/igniti…TurboFan是一个编译器,可以将字节码编译为CPU可以直接执行的机器码;


  • 如果一个函数被多次调用,那么就会被标记为热点函数,那么就会经过TurboFan转换成优化的机器码,提高代码的执行性能;


  • 但是,机器码实际上也会被还原为ByteCode,这是因为如果后续执行函数的过程中,类型发生了变化(比如sum函数原来执行的是number类型,后来执行变成了string类型),之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码;


  • TurboFan的V8官方文档:v8.dev/blog/turbof…上面是JavaScript代码的执行过程,事实上V8的内存回收也是其强大的另外一个原因,不过这里暂时先不展开讨论:


  • Orinoco模块,负责垃圾回收,将程序中不需要的内存回收;



Node.js架构


  • 我们编写的JavaScript代码会经过V8引擎,再通过Node.js的Bindings,将任务放到Libuv的事件循环中;


  • libuv(Unicorn Velociraptor—独角伶盗龙)是使用C语言编写的库;


  • libuv提供了事件循环、文件系统读写、网络IO、线程池等等内容;


网络异常,图片无法展示
|


Nodejs的全局对象


一些有用的全局对象。


  • __dirname:获取当前文件所在的文件夹的绝对路径


  • __filename:获取当前文件的绝对路径:


  • process对象:


  • cwd(): 获取当前终端运行的文件夹绝对路径。


  • argv:获取在终端执行时传入的参数。


  • env:获取当前程序的环境变量。


Node.js模块化


Node中对CommonJS进行了支持和实现,让我们在开发node的过程中可以方便的进行模块化开发:


  • 在Node中每一个js文件都是一个单独的模块;


  • 这个模块中包括CommonJS规范的核心变量:exports、module.exports、require


  • exportsmodule.exports可以负责对模块中的内容进行导出;


  • require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容; 下面我们将来介绍exports、module.exports、require的使用。


  • exports是一个对象,我们可以在这个对象中添加很多个属性,添加的属性会导出;


  • 我们也可以通过module.exports直接导出一个对象。


  • 我们通过require()函数导入一个文件。并且该文件导出的变量。 下面来详细介绍一个module.exports


  • CommonJS中是没有module.exports的概念的;


  • 但是为了实现模块的导出,Node中使用的是Module的类,每一个模块都是Module的一个实例,也就是module;


  • 所以在Node中真正用于导出的其实根本不是exports,而是module.exports;


  • 因为module才是导出的真正实现者;


  • 并且内部将exports赋值给module.exports。 该方式的导入导出有一个特点。


具体请访问:juejin.cn/post/701299…


  • Node中的文件都运行在一个函数中。可以通过打印console.log(arguments.callee + "")来验证。


  • 导入导出是值的引用,如果导出的是一个基本数据类型值,那么导出文件改变该值,然后导入文件该变量的值也不会变。


  • 他是通过require 函数来导入的,只有在执行js代码才会知道模块的依赖关系。


  • 代码是同步执行的。


  • 模块多次引入,只会加载一次。每个module内部会存在一个loaded来确定是否被加载过


  • 代码循环引入的时候,深度优先来加载模块。然后再广度优先。


path模块


只介绍一些常用的API


由于不同操作系统可能使用不同的路径分隔符,所以join方法就非常有用。


  • resolve: 拼接路径。这个会根据传入的第一个路径前面是否有/,../,./来查找本地的完整目录,然后再拼接传入的其他路径。如果第一个传入的路径/开头的,那么将把路径拼接到当前执行文件的绝对路径后面。如果最后一个传入的路径通过/开头,那么我们将直接忽略前面传入的路径参数。


  • join:路径拼接。这个就是传入的是啥拼接的就是啥。傻瓜式拼接。但是也会根据../来拼接上一级


const { resolve, join } = require("path")
    const first = '/zhang';
    const second = "./hao" || '../hao'
    const third = './llm' || '/llm'
    console.log(resolve( first, second, third)) //C:\zhang\hao\llm || C:\hao\llm || C:\llm
    console.log(join(first, second, third)) // \zhang\hao\llm || \hao\llm || \zhang\hao\llm


网络异常,图片无法展示
|


  • dirname:获取文件的父文件夹;


  • basename:获取文件名;


  • extname:获取文件扩展名;


const path = require("path")
    const url = "c:/zh/study/nodejs/index.js";
    console.log(path.dirname(url))// c:/zh/study/nodejs 
    console.log(path.basename(url))// index.js
    console.log(path.extname(url))//.js


fs模块


fs模块大部分API的实现都有三种方法。


  • 方式一:同步操作文件:代码会被阻塞,不会继续执行;


  • 方式二:异步回调函数操作文件:代码不会被阻塞,需要传入回调函数,当获取到结果时,回调函数被执行;


  • 方式三:异步Promise操作文件:代码不会被阻塞,通过 fs.promises 调用方法操作,会返回一个Promise,可以通过then、catch进行处理;


方式一:同步操作文件


// 1.方式一: 同步读取文件
const state = fs.statSync('../foo.txt');
console.log(state);
console.log('后续代码执行');


方式二:异步回调函数操作文件


// 2.方式二: 异步读取
fs.stat("../foo.txt", (err, state) => {
  if (err) {
    console.log(err);
    return;
  }
  console.log(state);
})
console.log("后续代码执行");


方式三:异步Promise操作文件


// 3.方式三: Promise方式
fs.promises.stat("../foo.txt").then(state => {
  console.log(state);
}).catch(err => {
  console.log(err);
})
console.log("后续代码执行");


获取文件描述信息


const fs = require("fs");
    fs.stat("./01.hello.txt", (err, info) => {
      console.log(info)
      console.log(info.isFile())// 判断他是否为文件
      console.log(info.isDirectory())// 判断他是否为文件夹
    })


网络异常,图片无法展示
|


文件描述符


在 POSIX 系统上,对于每个进程,内核都维护着一张当前打开着的文件和资源的表格。

每个打开的文件都分配了一个称为文件描述符的简单的数字标识符。


在系统层,所有文件系统操作都使用这些文件描述符来标识和跟踪每个特定的文件。


Windows 系统使用了一个虽然不同但概念上类似的机制来跟踪资源。


为了简化用户的工作,Node.js 抽象出操作系统之间的特定差异,并为所有打开的文件分配一个数字型的文件描述符


const fs = require("fs");
    fs.open("./01.hello.txt", (err, fd) => {
      if (err) {
        console.log(err)
      } else {
        console.log(fd) // fd是一个数字。
        fs.promise.readFile(fd).then(res => {
          console.log(res)
        })
      }
    })


文件读写


fs.readFile(path[, options], callback):读取文件的内容;

fs.writeFile(file, data[, options], callback):在文件中写入内容;


const fs = require("fs");
    fs.writeFile("./01.hello.txt", "加入文件", { encoding: 'utf-8', flag: 'a+' }, (err, res) => {
      if (err) {
        console.log(err)
      } else {
        console.log(res)
      }
    })


调用读写API很简单就可以操作文件,下面我们来说明一些options选项。


encoding:指定编码格式。注意如果读取文件和写入文件的编码格式不同,将会乱码。一般都采用utf-8编码。如果文件读取不指定编码格式,那么它将返回Buffer数据。


flag: 用于指定文件写入的方式。带有+的flag都可以读写。除了r+文件不存在,读取和写入会报出异常,其他的+flag都可以自动创建。


网络异常,图片无法展示
|


文件夹操作


  • 使用fs.mkdir()或fs.mkdirSync()创建一个新文件夹。


const dirname = './zh';
    if (!fs.existsSync(dirname)) { // 判断文件夹是否存在
      fs.mkdir(dirname, err => {
        console.log(err);
      });
    }


  • fs.readdir(), fs.readdirSync()读取文件夹中的所有文件和文件夹


fs.readdir(dirname, (err, files) => {
      console.log(files);
    });


  • rename()重命名文件夹


fs.rename("./zh", "./llm", err => {
      console.log(err);
    })


兄弟们,熟练掌握文件操作,可以写很多方便的脚本。


相关文章
|
3月前
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
930 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
4月前
|
缓存 监控 JavaScript
Vue.js 框架下的性能优化策略与实践
Vue.js 框架下的性能优化策略与实践
|
4月前
|
Web App开发 JSON JavaScript
Node.js 中的中间件机制与 Express 应用
Node.js 中的中间件机制与 Express 应用
|
4月前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
86 2
|
4月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
59 1
JavaScript中的原型 保姆级文章一文搞懂
|
8月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
150 2
|
4月前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
40 0
|
8月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的小区物流配送系统附带文章源码部署视频讲解等
219 5
|
8月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的家政平台附带文章源码部署视频讲解等
100 3
|
8月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的宠物援助平台附带文章源码部署视频讲解等
116 4

热门文章

最新文章