如何理解 resolve(Promise.resolve())内部执行了什么

new Promise((resolve, reject) => {
  console.log("async1 start");
  console.log("async2");
  resolve(Promise.resolve());
}).then(() => {
  console.log("async1 end");
});

new Promise(function(resolve) {
  console.log("promise1");
  resolve();
}).then(function() {
  console.log("promise2");
}).then(function() {
  console.log("promise3");
}).then(function() {
  console.log("promise4");
});

执行结果如下:

async1 start
async2
promise1
promise2
promise3
async1 end
promise4


求大神解释结果为什么是这样的?

阅读 8.1k
4 个回答

谢邀,好久不玩这玩意了。
只对 Chrome 与 Node 最新版本给出自己的一些理解,其他浏览器实现略有差异。

先来一张Typescript中对Promise的定义

clipboard.png

我们发现对resolve的类型定义中,接受的参数有PromiseLike这么个玩意,专业术语叫thenable,用人话说就是可以带有then方法的对象。

resolve在想,老子接受到一个thenable,这样输入具有兼容性,但是输出一定要确定(不确定会被打)。所以要把这个thenable包装一下,转为正规的Promise。但是这货又比较懒,不想判断这个thenable到底是真的Promise,还是PromiseLike,就所有的都包装一下,类似下面这样

clipboard.png

再来一张
clipboard.png

按照A-B-A-B的顺序来,然后我们模拟一下你问题中的形式

clipboard.png

你问题中的顺序

clipboard.png

Promise.resolve()返回一个新Promise对象,这时外面的resolve不会直接产生then,而会去检查这个Promise,导致了延迟

你确定你这个执行结果是正确的?我在chrome下执行了一下,结果如下:

async1 start
async2
promise1
async1 end
promise2
promise3
promise4

这样的结果是说的通的,Promise的构造函数会立即执行,resolve回调函数会被放在job queue中等待主任务队列完成后依次执行,可以参考我的文章

图片描述
chrome 版本 70.0.3538.77

似乎firefox下结果不一样:
图片描述
firefox 版本 63.0.1

补充一片文章来解释

这个应该是因为在上面的resolve里面返回了promise.resolve(),这也是一个Promise对象,导致的延迟执行,但是不同浏览器在执行相关处理时候的顺序有时候是不一样的。

推荐问题
宣传栏