Eventloop 是指浏览器或node的一种解决javaScript单线程运行时,不会阻塞的一种机制 也就是我们经常使用异步的原理
在js中 任务被分为两种
一种是宏任务(MacroTask):setTimeout,setInterval
一种是微任务(MicroTask): process.nextTick,Promise.then
同步任务在栈中先执行,进入主线程,异步任务进入任务队列,根据异步事件类型,进入对应的宏任务队列或者微任务队列中, 当执行栈为空的时候 主线程会查看队列是否有微任务存在,如果存在,会依次执行队列中的回调, 直到微任务队列为空,再去宏任务队列取出最前面的事件,加入当前执行栈 。当前执行栈执行完毕时,会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。
setTimeout(() => {
console.log('延时 1 秒');
},1000)
console.log("开始")
输出结果为//开始
//延时 1 秒
setTimeout 函数是宏任务,且是异步任务,因此会将函数放入任务队列(Event Queue)中,等待同步任务console.log(“开始”)执行结束后,读取任务队列 中 setTimeout 的回调函数执行。
setTimeout(function() {
console.log('1');
},1000)
new Promise(function(resolve) {
console.log('2');
}).then(function() {
console.log('3');
})
console.log('4');
// 输出结果为 2 4 1
1、首先 setTimeout,1 秒后将回调函数放入宏任务的 Event Queue 中
2、new Promise 同步代码,立即执行 console.log(‘2’),然后看到微任务 then,因此
将其放入微任务的 Event Queue 中
3、接下来执行同步代码 console.log(‘4’)
4、主线程的宏任务,已经执行完毕,接下来要执行微任务,因此会执行 Promise.then,到此,第一轮事件循环执行完毕
5、第二轮事件循环开始,先执行宏任务setTimeout 的回调函数,然后查找是否有微任务,没有,事件循环结束
总结 : 事件循环先执行宏任务,其中同步任务立即执行,异步任务加载到对应的 Event Queue 中,微任务也加载到对应的微任务的 Event Queue 中,所有的同步任务执行完之后,如果发现微任务队列中有未执行完的任务,执行他们,这样算是完成了一轮事件循环。接下来查看宏任务的队列中是否有异步代码,有的话执行第二轮的事件循环
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
// 执行结果为 1、2、4、3、5
1、宏任务同步代码 console.log(‘1’)
2、setTimeout,加入宏任务 Event Queue,没有发现微任务,第一轮事件循环走完
3、第二轮事件循环开始,先执行宏任务,从宏任务 Event Queue 中独取出 setTimeout 的回调函数
4、同步代码 console.log(‘2’),发现 process.nextTick,加入微任务 Event Queue
5、new Promise,同步执行 console.log(‘4’),发现 then,加入微任务 Event Queue
6、宏任务执行完毕,接下来执行微任务,先执行 process.nextTick,然后执行 Promise.then
7、微任务执行完毕,第二轮事件循环走完,没有发现宏任务,事件循环结束