nodejs中事件循环中的执行顺序
nodejs 事件循环是一个典型的生产者/消费者模型,异步 I/O、网络请求等是事件的生产者,源源不断为 Node 提供不同类型的事件,这些事件被传递到对应的观察者那里,事件循环则从观察者那里取出事件并处理。
事件循环、观察者、请求对象、I/O 线程池共同构成了 Node 异步 I/O 模型的基本要素。
Node 异步 I/O 几个关键词:单线程、事件循环、观察者、I/O 线程池,JavaScript 是单线程,node自身是多线程,只是 I/O 线程使用的 CPU 较少。除了用户代码无法并行执行外,所有的 I/O(磁盘 I/O 和网络 I/O 等)是可以并行起来的。
node 中还存在一些与 I/O 无关的异步 API,setTimeout()、setInteval()、setImmediate()、process.nextTick()
process.nextTick()=> idle 观察者
setImmediate() => check 观察者
事件循环对观察者的检查有先后顺序,idle观察者先于 I/O 观察者,I/O 观察者先于 check 观察者。
const fs = require("fs"); const path = require("path"); const wait = () => new Promise((resolove, reject) => { setTimeout(resolove(true), 3); }); fs.readFile( path.resolve(__dirname, "./limit.js"), "utf-8", async (err, data) => { console.log("读取的文件内容1"); } ); fs.readFile( path.resolve(__dirname, "./limit.js"), "utf-8", async (err, data) => { console.log("读取的文件内容2"); await wait(); console.log("读取文件内容2,等待3 秒后输出"); process.nextTick(() => { console.log("读取文件内容2,等待3 秒后执行 process.nextTick"); }); } ); console.log("start"); setTimeout(function () { console.log("setTimeout-1"); process.nextTick(function () { console.log("setTimeout-1-process.nextTick"); }); new Promise(function (resolve) { console.log("setTimeout-1-Promise"); resolve(); }).then(function () { console.log("setTimeout-1-Promise-then"); }); }); setImmediate(() => { console.log("setImmediate-1"); process.nextTick(function () { console.log("setImmediate-1-process.nextTick-1"); }); }); setImmediate(() => { console.log("setImmediate-2"); }); process.nextTick(function () { console.log("process.nextTick-1"); }); process.nextTick(function () { console.log("process.nextTick-2"); }); new Promise(function (resolve) { console.log("Promise-1"); resolve(); }).then(function () { console.log("Promise-1-then"); }); setTimeout(function () { console.log("setTimeout-2"); process.nextTick(function () { console.log("setTimeout-2-process.nextTick"); }); new Promise(function (resolve) { console.log("setTimeout-2-Promise"); resolve(); }).then(function () { console.log("setTimeout-2-Promise-then"); }); }); // 执行结果 // start // Promise-1 // 在每轮循环中,会将 process.nextTick 全部执行完,优先级> promise.then // process.nextTick-1 // process.nextTick-2 // Promise-1-then // setTimeout timer 优先级> setImmediate check 观察者 // setTimeout-1 // setTimeout-1-Promise // setTimeout-1-process.nextTick // setTimeout-1-Promise-then // setTimeout-2 // setTimeout-2-Promise // setTimeout-2-process.nextTick // setTimeout-2-Promise-then // 一次循环只执行一个 setImmediate // setImmediate-1 // setImmediate-1-process.nextTick-1 // setImmediate-2 // 读取的文件内容1 // 读取的文件内容2 // 读取文件内容2,等待3 秒后输出 // 读取文件内容2,等待3 秒后执行 process.nextTick