关于 Promise,判断以下代码的输出
更多描述
Promise.resolve()
.then(() => {
console.log(0);
return Promise.resolve(4);
})
.then((res) => {
console.log(res);
});
Promise.resolve()
.then(() => {
console.log(1);
})
.then(() => {
console.log(2);
})
.then(() => {
console.log(3);
})
.then(() => {
console.log(5);
})
.then(() => {
console.log(6);
});
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 727
Author 回答者: okbug
0 1 2 3 4 5 6 ?
Author 回答者: liweinanone
可以解释一下为什么吗? 我的错误答案是: 0 1 2 3 5 6 4
Author 回答者: mengliren666
0142356
Author 回答者: 9527YL
0 1 2 3 4 5 6
Author 回答者: wangjs-jacky
之前看过PromiseA+源码,结果碰上这道题还是理解,我给大家找到了相应的知乎解答:https://www.zhihu.com/question/453677175。
这边,我来阐述下我的理解:
顺序执行 0 和 1 应该大家都没什么问题,所以现在问题变成了为什么return Promise 为什么产生了 2 次微任务?
知乎评论里有人说:根据 promise/A+ ,结果应该为 0 1 2 4 3 5 6 ,也就是根据Promise/A++ 标准只产生了1次微任务。
按照PromiseA+的规范,此处应该是2.3.2标准:If x is a promise
,根据A+准则的源码是以这么处理的:
- 遇到.then就创建一pending状态的Promise保存起来。
- 如果是一个普通的number类型,则直接用Promise.resolve(number)即可。 如果是 promise类型的话,需要做一个状态同步操作,代码如下: 其中 x 是接收的已经resolved 的 Promise,即(Promise.resolve(4)),而this指向我们刚创建的 pending 状态的 Promise
resolveWithPromise(x) {
x.then(
result => {
this.resolve(result); // promise将结果给resolve
},
reason => {
this.reject(reason);
}
);
也就是说,这1个micro task的作用就是同步状态。
至于还有一个微任务的产生原因是来自:v8和PromiseA+规范的差异。
v8中的Promie实现是通过C++编写的,与promise/A+规范的不同之处在于,v8并没有对x is a promise
的情况做处理,而是只有对x is an object
的处理。所以多了一步micro task:作用就是将 resolveWithPromise => resolveWithThenableObject,伪代码如下:
if(x instanceOf MyPromise){
createPromiseResolveThenableJob // + micro task
}
========================================================================
以上仅仅只是我阅读知乎后的粗略理解,如果有说的不对的望指正!
面试的时候只需要简单记住:如果resolve()的括号内的结果是一个promise的话,会多执行两个micro task
类似的题目有:
new Promise((resolve) => {
let resolvedPromise = Promise.resolve();
resolve(resolvedPromise);
}).then(() => {
console.log("resolvePromise resolved");
});
Promise.resolve()
.then(() => {
console.log("promise1");
})
.then(() => {
console.log("promise2");
})
.then(() => {
console.log("promise3");
});
结果是:‘resolvePromise resolved’ 是在 ‘promise2’ 后面打印出来的。