EventLoop的过程:
1、先执行同步任务,异步任务交给对应API处理(比如XHR,Promise)。
2、异步任务结束后,会把回调函数放进宏任务或者微任务的队列。
3、但同步任务完成后,先清空微任务队列(微任务创建的微任务也会立即执行),后清空宏任务队列。
4、到此一次EventLoop结束。若有其它函数调用,则回1,从头开始,没函数调用就歇着了啊,不会有什么奇怪的操作。
特殊知识点:
-
清空微任务队列的时候,所执行的函数不断的往微任务队列里塞函数,新塞进来的也会一并执行,知道队列清空。比如一个Promise.then()中创建了另一个Promise.then()。宏任务不会这样啊! 宏任务中创建宏任务,会等到下一次eventLoop。例如:
console.log('script start'); // 1 setTimeout(function() { console.log('setTimeout');//5 if (typeof window !== 'undefined' ) { window.requestAnimationFrame(() => { console.log('Browser Event Loop 跑一圈了啊~'); }); } setTimeout(() => { console.log('setTimeout2'); }); Promise.resolve().then(function() { console.log('宏任务中创建的微任务他来了!!!!'); }) }, 0); Promise.resolve().then(function() { console.log('promise1');//3 }).then(function() { console.log('promise2');//4 }); console.log('script end');//2 /** script start script end promise1 promise2 setTimeout 宏任务中创建的微任务他来了!!!! Browser Event Loop 跑一圈了啊~ setTimeout2 */ -
老nodeJS和 >11 nodejs 的区别: 宏任务中创建的 微任务在 > 11 时会立即执行,<11时,会等到当前可执行的宏任务全部执行后再执行。浏览器行为和 > 11 相同 ,看上面那段代码,有例子。
-
浏览器渲染UI的时间点: 每次event loop的最后,会有一个UI render步骤。
-
await 可以这样理解:
async function f() { await p console.log('ok') } // 可简化理解为: function f() { return RESOLVE(p).then(() => { console.log('ok') }) } -
Chrome 对 await 执行时机的调整,这个不用管!在某些老版本的V8中,曾经对await的定义进行了调整。现在根据根据 TC39,await将直接使用Promise.resolve()相同语义,Node.js/Chrome已经统一了行为。
-
Nodejs中 process.nextTick,这个API很强大,他能在当前阶段结束后强行执行一个函数。在同步任务中调用,就在同步任务结束后调用;在微任务中调用,就在微任务队列清空后调用;宏任务同理。详见 blog.insiderattack.net/promises-ne…