介绍 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', ...)。