尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

HoRain云--Node.js 事件循环

HoRain云--Node.js 事件循环 事件循环是 Node.js 处理非阻塞 I/O 操作的核心机制使得单线程能够高效处理多个并发请求。Node.js 是基于单线程的 JavaScript 运行时利用事件循环来处理异步操作如文件读取、网络请求和数据库查询。事件循环使得 Node.js 能够非阻塞地运行代码、处理多个连接、以及执行异步 I/O 操作。事件循环使得 Node.js 能够处理大量并发的 I/O 操作而不会导致线程阻塞这是 Node.js 高效处理并发请求的关键。事件循环的阶段事件循环分为多个阶段每个阶段处理特定的任务。关键阶段如下Timers执行setTimeout()和setInterval()的回调。I/O Callbacks处理一些延迟的 I/O 回调。Idle, prepare内部使用不常见。Poll检索新的 I/O 事件执行与 I/O 相关的回调。Check执行setImmediate()回调。Close Callbacks处理关闭的回调如socket.on(close, ...)。事件循环的流程任务进入事件循环队列。事件循环按照阶段顺序进行处理每个阶段有自己的回调队列。事件循环会在poll阶段等待新的事件到达如果没有事件会检查其他阶段的回调。如果setImmediate()和setTimeout()都存在setImmediate()在check阶段先执行而setTimeout()在timers阶段执行。实例setTimeout(() {console.log(Timeout callback);}, 0);setImmediate(() {console.log(Immediate callback);});console.log(Main thread execution);输出顺序Main thread execution先打印。setImmediate()和setTimeout()的执行顺序取决于当前事件循环的状态一般setImmediate()会先执行。宏任务与微任务宏任务setTimeout、setInterval、setImmediate、I/O 操作等。微任务process.nextTick、Promise.then。执行顺序微任务优先级高于宏任务会在当前阶段的回调结束后立即执行。实例setTimeout(() {console.log(Timeout callback);}, 0);Promise.resolve().then(() {console.log(Promise callback);});console.log(Main thread execution);执行输出结果Main thread execution Promise callback Timeout callbackprocess.nextTick()process.nextTick() 会在当前操作结束后、下一个阶段开始前执行微任务优先级高于 Promise。实例process.nextTick(() {console.log(Next tick callback);});console.log(Main thread execution);输出Main thread execution Next tick callback事件驱动程序在 Node.js 中事件驱动编程主要通过 EventEmitter 类来实现。EventEmitter 是一个内置类位于 events 模块中通过继承 EventEmitter你可以创建自己的事件发射器并注册和触发事件。通过这种机制Node.js 可以高效地处理异步任务即使在单线程的环境下也能实现并发处理。整个事件驱动的流程就是这么实现的非常简洁。有点类似于观察者模式事件相当于一个主题(Subject)而所有注册到这个事件上的处理函数相当于观察者(Observer)。基本概念事件在程序中发生的动作或状态改变例如一个文件读取完成或一个 HTTP 请求到达。事件触发器EventEmitter是 Node.js 的内置模块用来发出和监听事件。事件处理器与事件关联的回调函数事件发生时被调用。事件驱动的流程注册事件在程序中通过EventEmitter实例注册事件和对应的处理器。触发事件当指定的事件发生时EventEmitter会触发该事件。处理事件事件循环会调度相应的回调函数来执行任务。Node.js 有多个内置的事件我们可以通过引入 events 模块并通过实例化 EventEmitter 类来绑定和监听事件如下实例// 引入 events 模块 var events require(events); // 创建 eventEmitter 对象 var eventEmitter new events.EventEmitter();以下程序绑定事件处理程序// 绑定事件及事件的处理程序 eventEmitter.on(eventName, eventHandler);我们可以通过程序触发事件// 触发事件 eventEmitter.emit(eventName);实例创建 hello.js 文件代码如下所示实例 1const EventEmitter require(events);const myEmitter new EventEmitter();// 注册事件处理器myEmitter.on(greet, () {console.log(Hello, world!);});// 触发事件myEmitter.emit(greet);输出Hello, world!创建 main.js 文件代码如下所示实例 2// 引入 events 模块 var events require(events); // 创建 eventEmitter 对象 var eventEmitter new events.EventEmitter(); // 创建事件处理程序 var connectHandler function connected() { console.log(连接成功。); // 触发 data_received 事件 eventEmitter.emit(data_received); } // 绑定 connection 事件处理程序 eventEmitter.on(connection, connectHandler); // 使用匿名函数绑定 data_received 事件 eventEmitter.on(data_received, function(){ console.log(数据接收成功。); }); // 触发 connection 事件 eventEmitter.emit(connection); console.log(程序执行完毕。);接下来让我们执行以上代码$ node main.js 连接成功。 数据接收成功。 程序执行完毕。Node 应用程序是如何工作的在 Node 应用程序中执行异步操作的函数将回调函数作为最后一个参数 回调函数接收错误对象作为第一个参数。接下来让我们来重新看下前面的实例创建一个 input.txt ,文件内容如下菜鸟教程官网地址www.runoob.com创建 main.js 文件代码如下var fs require(fs); fs.readFile(input.txt, function (err, data) { if (err){ console.log(err.stack); return; } console.log(data.toString()); }); console.log(程序执行完毕);以上程序中 fs.readFile() 是异步函数用于读取文件。 如果在读取文件过程中发生错误错误 err 对象就会输出错误信息。如果没发生错误readFile 跳过 err 对象的输出文件内容就通过回调函数输出。执行以上代码执行结果如下程序执行完毕 菜鸟教程官网地址www.runoob.com接下来我们删除 input.txt 文件执行结果如下所示程序执行完毕 Error: ENOENT, open input.txt因为文件 input.txt 不存在所以输出了错误信息。
返回列表