js 事件循环 Event Loop

宏任务: script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务: process.nextTick(Nodejs), Promises, Object.observe, MutationObserver;

setTimeout(()=>{ console.log("setTimeout1"); Promise.resolve().then(data => { console.log(222); }); }); setTimeout(()=>{ console.log("setTimeout2"); }); Promise.resolve().then(data=>{ console.log(111); }); //运行结果如下 111 setTimeout1 222 setTimeout2/*每一个主体代码执行 先执行宏任务 宏任务包括 setTimeOut会产生任务队列 不会立即执行,继续向下运行,直到最后一个函数,如果遇到新的宏任务,又添任务队列后方添加任务, 当主体代码执行完毕 ,把外部位promise等微任务如执行完毕,再从上向下执行宏任务,如果队列中的宏任务执行中也有任务队列,再次循环,宏任务完成后,执行微任务。 */

【js 事件循环 Event Loop】1.主线程上没有需要执行的代码
2.接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在下一次的事件循环中执行)。
3.接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在再下一次的事件循环中执行)。
4.首先检查微任务队列, 即 microtask队列,发现此队列不为空,执行第一个promise的then回调,输出 '111'。
此时microtask队列为空,进入下一个事件循环
5.检查宏任务队列,发现有 setTimeout的回调函数,立即执行回调函数输出 'setTimeout1',检查microtask 队列,发现队列不为空,执行promise的then回调,输出'222',microtask队列为空,进入下一个事件循环。
6.检查宏任务队列,发现有 setTimeout的回调函数, 立即执行回调函数输出'setTimeout2'。
例子 2:
console.log('script start'); setTimeout(function () { console.log('setTimeout---0'); }, 0); setTimeout(function () { console.log('setTimeout---200'); setTimeout(function () { console.log('inner-setTimeout---0'); }); Promise.resolve().then(function () { console.log('promise5'); }); }, 200); Promise.resolve().then(function () { console.log('promise1'); }).then(function () { console.log('promise2'); }); Promise.resolve().then(function () { console.log('promise3'); }); console.log('script end'); 运行结果为: script start script end promise1 promise3 promise2 setTimeout---0 setTimeout---200 promise5 inner-setTimeout---0

1.首先顺序执行完主进程上的同步任务,第一句和最后一句的console.log
2.接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中(这个任务在下一次的事件循环中执行)。
3.接着遇到setTimeout 200,它的作用是在 200ms 后将回调函数放到宏任务队列中(这个任务在再下一次的事件循环中执行)。
4.同步任务执行完之后,首先检查微任务队列, 即 microtask队列,发现此队列不为空,执行第一个promise的then回调,输出 'promise1',然后执行第二个promise的then回调,输出'promise3',由于第一个promise的.then()的返回依然是promise,所以第二个.then()会放到microtask队列继续执行,输出 'promise2';
5.此时microtask队列为空,进入下一个事件循环, 检查宏任务队列,发现有 setTimeout的回调函数,立即执行回调函数输出 'setTimeout---0',检查microtask 队列,队列为空,进入下一次事件循环.
6.检查宏任务队列,发现有 setTimeout的回调函数, 立即执行回调函数输出'setTimeout---200'.
接着遇到setTimeout 0,它的作用是在 0ms 后将回调函数放到宏任务队列中,检查微任务队列,即 microtask 队列,发现此队列不为空,执行promise的then回调,输出'promise5'。
7.此时microtask队列为空,进入下一个事件循环,检查宏任务队列,发现有 setTimeout 的回调函数,立即执行回调函数输出,输出'inner-setTimeout---0'。代码执行结束
为什么会需要event-loop? 因为 JavaScript 是单线程的。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。为了协调事件(event),用户交互(user interaction),脚本(script),渲染(rendering),网络(networking)等,用户代理(user agent)必须使用事件循环(event loops

    推荐阅读