重学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);
    })


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


相关文章
|
25天前
|
开发框架 JavaScript 安全
js开发:请解释什么是Express框架,以及它在项目中的作用。
Express是Node.js的Web开发框架,简化路由管理,支持HTTP请求处理。它采用中间件系统增强功能,如日志和错误处理,集成多种模板引擎(EJS、Jade、Pug)用于HTML渲染,并提供安全中间件提升应用安全性。其可扩展性允许选用合适插件扩展功能,加速开发进程。
|
10天前
|
开发框架 JavaScript 中间件
node+express搭建服务器环境
node+express搭建服务器环境
node+express搭建服务器环境
|
4天前
|
JavaScript 关系型数据库 MySQL
❤Nodejs 第二章(Node连接本地数据库)
【4月更文挑战第2天】本文介绍了如何使用Node.js连接本地MySQL数据库。首先,提到了在MySQL官网下载安装数据库和使用Navicat for MySQL进行数据库管理。接着,通过`yarn add mysql`在项目中安装数据库依赖。然后,创建`app.js`文件,设置数据库连接参数,并建立连接进行查询操作。遇到导入模块的错误后,修改导入方式为CommonJS语法。
17 1
|
7天前
|
开发框架 JavaScript 前端开发
【Node系列】Express 框架
Express.js 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,提供一系列强大的特性来帮助你创建各种 web 和移动设备应用。
23 2
|
1月前
|
JavaScript 前端开发 Serverless
函数计算新功能— 支持 Node.js 18 、Node.js 20 运行时
从2024年2月起,函数计算正式发布 Node.js 18 运行时和 Nodejs.20 运行时,函数计算2.0和函数计算3.0都支持新的运行时,目前新运行时处在公测状态,欢迎大家来体验。
454 0
|
1月前
|
Web App开发 JavaScript 前端开发
使用Node.js和Express构建RESTful API
使用Node.js和Express构建RESTful API
16 0
|
2月前
|
JSON JavaScript 前端开发
JS服务端技术—Node.js知识点
本篇文章是我开始系统学习Node.js的一些笔记。如果文中阐述不全或不对的,多多交流。
62 0
JS服务端技术—Node.js知识点
|
3月前
|
JavaScript
node下的two.js调用one.js出现无法编译问题 Cannot find module ‘c:
node下的two.js调用one.js出现无法编译问题 Cannot find module ‘c:
47 0
|
3月前
|
JavaScript
Turndown 源码分析:五、节点相关`root-node.js`和`node.js`
Turndown 源码分析:五、节点相关`root-node.js`和`node.js`
|
2月前
|
消息中间件 Web App开发 JavaScript
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
70 0