纯JS中的Promise.resolve与new Promise(resolve)的区别

5

相关问题告诉我,将Promise解决为一个新的Promise,即使它立即被解决,也会在下一个循环中调度。然而,评论部分似乎是反例。

var p1 = Promise.resolve("p1")

/* console order will be "p2" "p1" */ 
// pattern1
// var p2 = Promise.resolve(Promise.resolve("p2")); 
// pattern2
// var p2 = Promise.resolve(new Promise(function(resolve, reject){
//   resolve("p2")
// }))

/* console order will be "p1" "p2" */ 
// pattern3
var p2 = new Promise(function(resolve, reject){
    resolve(Promise.resolve("p2"));
}) 

p2.then(function(value){
  console.log(value);
})
p1.then(function(value){
  console.log(value);
})

在Chrome v61.0.3163.91版本中表现奇怪,但在Node.js中正常。 注意:这个问题与流行的问题不同。只关注顺序问题:为什么不同的模式产生不同的顺序?最好用事件循环的术语来解释。

@JaromandaX 在这里记录了“p1”、“p2”,Chromium 60和Firefox 57都是如此。 - guest271314
@JaromandaX 不是。哪一个?我仍然没有明白实际问题是什么? - guest271314
@JaromandaX 这段被注释的代码记录了代码调用的顺序。无论是先记录 "p1" 还是 "p2" 取决于哪个 .then() 先被调用。 - guest271314
哦...是啊...算了我的注释,测试错了 :p - Jaromanda X
2个回答

3

promise.then的回调函数直到Promise状态已经被确定(完成或拒绝)后才会被添加到微任务队列中。微任务将按顺序从队列中执行,即“先进先出”。

在Chrome v61.0.3163.91的实现中,一旦创建p1,它就始终处于已解决的状态。pattern1pattern2中的p2处于已解决的状态,而pattern3中的p2处于挂起状态。

因此,在pattern1pattern2中,p2.then的回调函数首先被添加到微任务队列中并首先执行。在pattern3中,虽然p2.then首先执行,但由于Promise仍处于挂起状态,因此将来才将其回调函数附加到微任务队列中。所以p1.then的回调函数先执行。


0

注释中的.then()按照代码调用的顺序记录结果。

// logs `"p1"`, `"p2"`
var p1 = Promise.resolve("p1")

var p2 = Promise.resolve(Promise.resolve("p2")); 

p1.then(function(value){
  console.log(value);
})

p2.then(function(value){
  console.log(value);
})

// logs `"p2"`, `"p1"`
var p1 = Promise.resolve("p1")

var p2 = Promise.resolve(Promise.resolve("p2")); 

p2.then(function(value){
  console.log(value);
})

p1.then(function(value){
  console.log(value);
})


当然,但我猜楼主想知道为什么? - Jaromanda X
p2的3种不同模式之间的区别。这只是我对问题和操作代码中评论的解释。 - Jaromanda X
@JaromandaX 在 Promise 构造函数中多余的 Promise.resolve() 调用是这些模式之间的区别。移除额外的 Promise.resolve() 后,结果应该是 "p2", "p1" `var p1 = Promise.resolve("p1")var p2 = new Promise(function(resolve, reject){ resolve( "p2" ); }); p2.then(function(value){ console.log(value); })p1.then(function(value){ console.log(value); })`. 如果这些模式被标记,我们就可以清楚地知道我们正在引用哪些代码,这可能会有所帮助。 - guest271314
2
是啊...但为什么 var p2 = new Promise(function(resolve, reject){ resolve(Promise.resolve("p2")); })var p2 = Promise.resolve(new Promise(function(resolve, reject){ resolve("p2") })) 不同 - 我本来期望所有三个输出都是 p2 然后是 p1 (就像在 node 中一样)。 - Jaromanda X
1
@PageYe 区别在于 p2Promise 构造函数内部调用了 Promise.resolve()。当代码是 var p2 = new Promise(function(resolve, reject){ resolve("p2"); }) 时,"p2" 首先被记录在控制台中。建议在 https://bugs.chromium.org/p/monorail/issues/list 提交一个问题,向 Chromium 浏览器中 Promise 的实现者询问具体细节和解释。 - guest271314
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接