有这么一道题:
setTimeout(function() {
console.log(1)
}, 0);
new Promise(function(resolve, reject) {
console.log(2)
for (var i = 0; i < 10000; i++) {
if(i === 10) {console.log(10)}
i == 9999 && resolve();
}
console.log(3)
}).then(function() {
console.log(4)
})
console.log(5);
结果是怎样的呢?
真正结果是: 2 10 3 5 4 1
,不知你写对了没有。如果你的答案错了,没关系,接着往下读,会为你一一解惑。
这里涉及到三个“何时”:
下面我们来一一分析。
我们知道,JavaScript是基于事件驱动单线程执行的,所有任务都需要排队,也就是说前一个任务结束,才会去执行下一个任务。而像settimeout、ajax等异步操作的回调,会进入”任务队列“中,而且只有主线程中没有执行任何同步代码的前提下,才会执行异步回调。
而settimeout(fn, 0)表示立即执行,也就是用来改变任务的执行顺序,要求浏览器”尽可能快“的进行回调。
我们依旧以上面代码为例:
new Promise(function(resolve, reject) {
console.log(2)
for (var i = 0; i < 10000; i++) {
if(i === 10) {console.log(10)}
i == 9999 && resolve();
}
console.log(3)
})
结果: 2 10 3
从结果可以看出,Promise
新建后立即执行,也就是说,Promise构造函数
里的代码是同步执行的。
看看实例:
new Promise(function(resolve, reject) {
console.log(2)
for (var i = 0; i < 10000; i++) {
if(i === 10) {console.log(10)}
i == 9999 && resolve();
}
console.log(3)
}).then(function() {
console.log(4)
})
for (var i = 0; i < 5; i++) {
console.log('a' + i);
}
结果: 2 10 3 a0 a1 a2 a3 a4 4
从结果来看,可以知道then
方法指向的回调将在当前脚本所有同步任务执行完后执行。
再来回顾第一个例子:
setTimeout(function() {
console.log(1)
}, 0);
new Promise(function(resolve, reject) {
console.log(2)
for (var i = 0; i < 10000; i++) {
if(i === 10) {console.log(10)}
i == 9999 && resolve();
}
console.log(3)
}).then(function() {
console.log(4)
})
console.log(5);
结果是:2 10 3 5 4 1
通过上面的实例,相信你已经解开了三个“何时
”。可能你还有一个疑惑,那就是为什么then
比setTimeout
执行的要早呢?
目前有两种原因导致:
其实,setTimeout有个最小执行时间
(minimum delay of 4ms
),并不是0s
执行的。
注:HTML5中已经将最小执行时间统一为4ms。
Macrotasks和Microtasks 都属于异步任务中的一种,常用api分类: macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering microtasks: process.nextTick, Promise, MutationObserver
一个事件循环中只有一个macrotask任务,可以有一个或多个microtask任务。
来看看上面实例的执行:
经过层层测试,所以最终得出的结论是: 同步代码(包括promise的构造函数) -> promise.then -> setTimeout
如有错误或疑问,欢迎在下方评论区留言!
参考文章: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop http://www.ruanyifeng.com/blog/2014/10/event-loop.html https://juejin.im/entry/5779bb0ac4c971005572ba29 https://www.zhihu.com/question/36972010/answer/71338002 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setTimeout https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ https://stackoverflow.com/questions/38752620/promise-vs-settimeout