宏工作: 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);});//运行后果如下111setTimeout1222setTimeout2/*每一个主体代码执行 先执行宏工作 宏工作包含 setTimeOut会产生工作队列 不会立刻执行,持续向下运行,直到最初一个函数,如果遇到新的宏工作,又添工作队列前方增加工作,当主体代码执行结束 ,把外部位promise等微工作如执行结束,再从上向下执行宏工作,如果队列中的宏工作执行中也有工作队列,再次循环,宏工作实现后,执行微工作。*/
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 startscript endpromise1promise3promise2setTimeout---0setTimeout---200promise5inner-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