Node.js 技术分享

2024-07-11 11 0

介绍 Node.js

Node.js 是一个开源与跨平台的 JavaScript 运行时环境

在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能

可以理解为 Node.js 就是一个服务器端的、非阻塞式I/O的、事件驱动的JavaScript运行环境

Nodejs采用了非阻塞型I/O机制,在做I/O操作的时候不会造成任何的阻塞,当完成之后,以回调函数的形式通知执行操作

例如在执行了访问数据库的代码之后,将立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率

事件驱动

Node采用了事件驱动机制,而EventEmitter就是Node实现事件驱动的基础

在EventEmitter的基础上,Node几乎所有的模块都继承了这个类,这些模块拥有了自己的事件,可以绑定/触发监听器,实现了异步操作

Node.js 里面的许多对象都会分发事件,比如 fs.readStream 对象会在文件被打开的时候触发一个事件

这些产生事件的对象都是 events.EventEmitter 的实例,这些对象有一个 eventEmitter.on() 函数,用于将一个或多个函数绑定到命名事件上

EventEmitter

Node的events模块只提供了一个EventEmitter类,这个类实现了Node异步事件驱动架构的基本模式——观察者模式

在这种模式中,被观察者(主体)维护着一组其他对象派来(注册)的观察者,有新的对象对主体感兴趣就注册观察者,不感兴趣就取消订阅,主体有更新的话就依次通知观察者们

const EventEmitter = require('events')

class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()

function callback(){
  console.log('触发了event事件!')
}

myEmitter.on('event', callback)
myEmitter.emit('event')

myEmitter.removeListener('event',callback);

fs

fs 模块是 Node.js 内置的,但它广泛使用 EventEmitter 来处理文件读取和写入事件。

const fs = require('fs');

const readstream = fs.createReadstream('./example.txt',{ encoding: 'utf8  });

readstream.on('data',(chunk)=>{
  console.log('读取到数据块:',chunk);
}

readstream.on('end',()=>{
  console.1og('文件读取完成');
});

readstream.on('error',(err)=>{
  console.error('读取文件时发生错误:,err);
});

http

Node.js 内置的 http 模块也使用 EventEmitter 来处理 HTTP 请求和响应事件。

const http = require('http');

const server = http.createserver((req,res)=>{
  res.statusCode=200;
  res.setHeader('Content-Type,"text/plain');
  res.end('Hello, world!\n');
});

server.on('request',(req,res)=>{
  console.log(`请求方法:${reg.method},清求URL:${req.url});
});

server.on('listening,()=>{
  console.log('服务器已启动,正在监听请求..);
});

server.listen(3000);

事件循环机制

NodeJS中,事件循环是基于libuv实现。EventLoop存在6个阶段,每个阶段对应一个队列,当事件循环进入某个阶段时, 将会在该阶段内执行回调,直到队列耗尽或者回调的最大数量已执行, 那么将进入下一个处理阶段

   ┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘

Timers 阶段:这个阶段执行 setTimeout 和 setInterval 的回调函数。

I/O Callbacks 阶段:这个阶段执行一些系统操作的回调函数,例如 TCP 错误类型的回调。

Idle, Prepare 阶段:仅在内部使用。

Poll 阶段:这个阶段是最重要的阶段,执行 I/O 回调函数,以及等待新的 I/O 事件。

Check 阶段:这个阶段执行 setImmediate 的回调函数。

Close Callbacks 阶段:这个阶段执行一些关闭事件的回调函数,例如 socket.on('close', ...)。