关于Promise.resolve(v)和new Promise(resolve => resolve(v))是否等价问题

3,182 阅读1分钟

借鉴在《ECMAScript 6 入门》一书中描述的内容,Promise.resolve('foo')等价于new Promise(resolve => resolve('foo'))。如果resolve的参数是一个promise对象呢,是否仍然等价?

Demo1

let p1 = Promise.resolve(1);
let p2 = new Promise(resolve => resolve(1));
console.log(p1);
console.log(p2);
// Promise {<fulfilled>: 1} 
// Promise {<fulfilled>: 1}

Demo2

let p = Promise.resolve(1);
let p3 = Promise.resolve(p);
let p4 = new Promise(resolve => resolve(p));
console.log(p3);
console.log(p4);
// Promise {<fulfilled>: 1}
// Promise {<pending>}

发现p3和p4的状态不一样了

Demo3

let p = Promise.resolve(1);
let p3 = Promise.resolve(p);
let p4 = new Promise(resolve => resolve(p));
p4.then(() => console.log('promise1'))
  .then(() => console.log('promise2'));
p3.then(() => console.log('promise3'))
  .then(() => console.log('promise4'))
  .then(() => console.log('promise5'));
// promise3
// promise4
// promise1
// promise5
// promise2

发现p4中指定的回调函数延迟了两个时序执行。再看Demo4相关的等价代码,推迟了两个时序的then执行。

Demo4

Promise.resolve(thenable)等价于new Promise(resolve => { Promise.resolve().then(()=>{ p.then(resolve); }); });

let p = Promise.resolve(1);
let p3 = Promise.resolve(p);
//Promise.resolve(thenable) 等价于如下代码
let p4 = new Promise(resolve => {
	Promise.resolve().then(()=>{
		p.then(resolve);
	});
});
p4.then(() => console.log('promise1'))
  .then(() => console.log('promise2'));
p3.then(() => console.log('promise3'))
  .then(() => console.log('promise4'))
  .then(() => console.log('promise5'));

在这里插入图片描述 第一次宏任务执行,遇到如上图选中的A区块,会将A加入到微任务队列,继续执行,接着会将() => console.log('promise3')加入到微任务队列,本次循环结束之前会执行微任务队列中的这两个回调函数。

A区块的执行会将resolve放入队列,() => console.log('promise3')执行打印出promise3;执行完毕会将() => console.log('promise4')放入队列,继续执行。

resolve执行,会通知p4状态改变为fulfilld,进而将() => console.log('promise1')放入队列,() => console.log('promise4')执行,打印出promise4,执行完毕会将() => console.log('promise5')放入队列。因此一次打印promise1promise5

参考

Promise.resolve()与new Promise(r => r(v))

async await 和 promise微任务执行顺序问题

What's the difference between resolve(thenable) and resolve('non-thenable-object')?