1、基本概念
1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
2. 主线程之外,还存在一个“任务队列”(task queue),只要异步
任务有了运行结果,就在“任务队列”中放置一个事件(包括事件绑定、ajax和定时器)。
3. 一旦“执行栈”中的所有同步任务执行完毕,系统就会读取“任务队
列”,看看里边有哪些事件。哪些对应的异步任务,于是结束等待
状态,进入“执行栈”开始执行。
4. 主线程不断重复上边的第三步。
2、 如果添加了Promise又如何工作呢?
我们知道,Promise的回调函数不是传入的,而是使用then来调用的。因此,Promise中定义的函数应该是马上执行的,then才是其回调函数,放入queue队列中。
在参考的文章中还提到了一个重要的概念:
macro-task包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver
执行顺序:函数调用栈清空只剩全局执行上下文,然后开始执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次执行macro-task中的一个任务队列,执行完之后再执行所有的micro-task,就这样一直循环。
再看一个例子:
(function test() {
setTimeout(function() {console.log(4)}, 0);
new Promise(function executor(resolve) {
console.log(1);
for( var i=0 ; i<10000 ; i++ ) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
})()
具体的过程可以看上面那篇文章。大概过程如下:
- 遇到setTimeout,交给其他模块执行,执行完后回调放入macro-task中
- 遇到Promise,立即执行里面的function,输出1。
- 循环开始,遇到resolve(),修改Promise状态为fulfill。继续执行,输出2。
- 遇到then,将回调放入micro-task中。
- 继续执行,输出3。
- call stack执行完毕了。开始执行micro-task中的回调函数,输出5。
- micro-task执行完毕,开始执行macro-task中的回调函数,输出4。
- 结束。
原文链接:https://blog.csdn.net/qq_31628337/article/details/71056294
参考:https://blog.csdn.net/qq_31628337/article/details/71056294
http://www.ruanyifeng.com/blog/2014/10/event-loop.html