事件循环背景

nodejs是基于v8引擎的JavaScript运行时

nodejs是基于libuv实现 异步非阻塞式i/o 操作的。
事件循环是nodejs处理非阻塞式I/O操作的机制

正常js执行顺序为:

1、主线程执行栈全部任务执行完毕。(同步任务)
2、检查微任务队列
2.1 process.nextTick优先级最高,总是最先执行
2.2 Promise的then回调;await 后面的内容
3、检查宏任务队列,提取一次任务推入执行栈,进行执行。

宏任务队列也就是事件循环分为6个阶段:

image.png

1.timers阶段 (setTimeout、setInterval)
2.I/O事件回调阶段(I/O callbacks)阶段
3.闲置阶段(idle, prepare):仅系统内部使用
4.轮询阶段(poll)
5.检查阶段(check):setImmediate()
6.close callbacks阶段:执行close事件回调

例题

例题1

console.log('main');

setImmediate(function() {
    console.log('setImmediate');
});

new Promise(function(resolve, reject) {
    resolve();
}).then(function() {
    console.log('promise.then');
});

1.console.log('main');加入同步队列
2.setImmediate(function() {
    console.log('setImmediate');
});加入宏任务中的检查阶段(check)
3.promise的回掉加入微任务队列中

image.png

例题2

async function async1() {
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}

async function async2() {
    console.log('async2')
}

console.log('script start') // 1.加入同步队列

setTimeout(function () {   // 2.加入宏任务的timer阶段
    console.log('setTimeout0')
}, 0)

setTimeout(function () { // 3.加入宏任务的timer阶段
    console.log('setTimeout2')
}, 300)

setImmediate(() => console.log('setImmediate')); // 4.加入宏任务的check阶段

process.nextTick(() => console.log('nextTick1'));  // 5.加入微任务队列

async1(); 
//6.执行async1
// 执行async1中的async2
// 把await async2()后的内容加入微任务队列

process.nextTick(() => console.log('nextTick2'));
// 7.加入微任务队列 process.nextTick优先级最高 所以提前

new Promise(function (resolve) {
    console.log('promise1') // 7.加入同步任务
    resolve();
    console.log('promise2') // 8.加入同步任务
}).then(function () {
    console.log('promise3') // 9.加入微任务
})
 
console.log('script end') // 10.加入同步任务

结果如下
script start
async1 start
async2
promise1
promise2
script end
nextTick1
nextTick2
async1 end
promise3
setTimeout0
setImmediate
setTimeout2

image.png


NANA
94 声望7 粉丝

小魔女