极客时间返利平台,你可以在上边通过山月的链接购买课程,并添加我的微信 (shanyue94) 领取返现。

# 关于 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 (opens new window)

Author

回答者: okbug (opens new window)

0 1 2 3 4 5 6 ?

可以解释一下为什么吗? 我的错误答案是: 0 1 2 3 5 6 4

0142356

Author

回答者: 9527YL (opens new window)

0 1 2 3 4 5 6

之前看过 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+准则的源码是以这么处理的:

  1. 遇到.then 就创建一 pending 状态的 Promise 保存起来。
  2. 如果是一个普通的 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' 后面打印出来的。

Last Updated: 2/23/2022, 11:56:07 AM