? ? ?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、微任务执行完毕,第二轮事件循环走完,没有发现宏任务,事件循环结束
|