nodejs中事件循环中的执行顺序

2022-11-21 09:19:09 浏览数 (1)

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 观察者。

代码语言:javascript复制
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

0 人点赞