一文讲清楚Node的事件循环

node Event LOOP

是什么:
  1. 使用libuv的I/O 处理
  • libuv是一个基于异步,事件驱动的跨平台抽象层
    是node的新跨平台抽象层
  • 核心是提供i/o的事件循环和异步回调
  1. 负责实现这种非阻塞行为,它使用应用程序线程调度挂起的任务。
  2. 在任务完成时发出一个事件,将需要处理的事件添加到事件队列。
  3. 对事件队列中的事件进行迭代,并安排何时执行其关联的回调函数
运行过程:

v8解析js代码->代码调用Node API->进入到libuv->不同任务分配到不同线程->以异步的方式将任务执行结果返回给V8引擎

Event Loop共分为6个阶段

来回执行(poll->check->close callback ->timer->i/o callbacks->idle,prepare)

具体阶段

在这里插入图片描述

  1. timers定时器 :执行 setTimeout 和 setInterval 到期的回调,并且由 poll 阶段控制的
  2. I/O pending callbacks待定回调:
    执行延迟到下一个循环迭代的I/O回调
    上一轮少数的callback会放在这一阶段执行,执行某些系统操作(例如TCP错误类型)的回调==】
  3. idle,prepare:系统内部使用
  4. poll轮询:
    执行pengding callback
    检索新的I/O事件
    遍历回调对列并执行(I/o回调)执行I/O回调
    除了关闭的回调函数,计时器和setImmediate调度的之外,其余均在此阻塞
    处理轮询队列中的事件,
    设定 timer 且poll 队列为空:判断是否有 timer 超时,超时则回到 timer 阶段执行回调
  5. check :
    setImmediate()的回调会被加入 check 队列中,执行顺序在 poll 阶段之后,执行setImmediate的回调
    如果队列为空,再执行setImmediate 回调。如果setImmediate 回调也没有(在check中),再等待回调被加入到队列尾部
  6. close callbacks:关闭socket.on(‘close’,…)等回调函数,执行close事件的callback

process.nextTick:每个阶段完成后,存在 nextTick 队列,就会清空队列中的所有回调函数,优先于其他 microtask 微任务执行

事件循环:在进程启动时,Node 便会创建一个类似于 while(true) 的循环,每执行一次循环体的过程我们成为 Tick。每个 Tick 的过程就是查看是否有事件待处理。如果有就取出事件及其相关的回调函数。然后进入下一个循环,如果不再有事件处理,就退出进程

代码执行过程

const { resolve } = require("path");

async function async1() {
    console.log('async1 started');
    await async2();
    console.log('async end');
}
async function async2() {
    console.log('async2');
}
console.log('script start.');
setTimeout(() => {
    console.log('setTimeout0');
    setTimeout(() => {
        console.log('setTimeout1');
    }, 0);
    setImmediate(() => {
        console.log('setImmediate');
    })
}, 0);
process.nextTick(() => {
    console.log('nextTick');
})
async1();
new Promise((resolve) => {
    console.log('promise1');
    resolve();
    console.log('promise2');
}).then(() => {
    console.log('promise.then')
});
console.log('script end.');
/**
 * script start.
 * async1 started
 * async2
 * promise1
 * promise2
 * script end.
 * nextTick
 * async end
 * promise.then
 * setTimeout0
 * setImmediate
 * setTimeout1
 */

解析
第一轮
宏任务1
输出
script start
async1 started: await中也是同步的代码
async2
promise1
promise2
script end
产生宏任务2:
setTimeout

产生微任务1:
process.nextTick
await下一行代码
promise.then

第二轮
微任务1
输出:
nextTick
async end
promise.then

第三轮
宏任务2
输出:
setTimeout0
产生宏任务3:
setTimeout1

产生微任务2:
setImmediate
第四轮
微任务2
setImmediate:setImmediate在定时器前

第五轮
宏任务3
输出:
setTimout1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值