为啥在 Promise.all() 之后不调用 onRejected,其中包含在数组中的 Promise.reject() 传递给 Promise.all()?

Posted

技术标签:

【中文标题】为啥在 Promise.all() 之后不调用 onRejected,其中包含在数组中的 Promise.reject() 传递给 Promise.all()?【英文标题】:Why is onRejected not called following Promise.all() where Promise.reject() included in array passed to Promise.all()?为什么在 Promise.all() 之后不调用 onRejected,其中包含在数组中的 Promise.reject() 传递给 Promise.all()? 【发布时间】:2016-05-04 16:22:35 【问题描述】:

给定

var promises = [Promise.resolve("a"), Promise.reject("b")];

Promise.all(promises.map(function(p, index) 
  return p.then(function(data) 
    console.log("inside .map()", data, "index", index)
    return data
  , function(err) 
    console.log(err);
    return err
  )
))
.then(function(complete) 
  console.log("all promises after .map()", complete)
, function(err) 
  console.log("err", err)
)

为什么onRejected 没有在.then(onFulfilled, onRejected) 之后调用Promise.all()

jsfiddle https://jsfiddle.net/9gprLc7q/

https://jsfiddle.net/9gprLc7q/

【问题讨论】:

因为您没有处理映射中的错误,所以您返回的仍然是已解决的承诺。如果你这样做Promise.reject(err),它将正常工作。 即使不重复也密切相关(但不是一个明显的):Chained promises not passing on rejection。你 return err 而不是 rethrowing。 【参考方案1】:

您需要了解,处理拒绝会导致将承诺重新推上成功之路。解决此问题的一种方法是重新抛出故障处理程序,如下所示:

var promises = [Promise.resolve("a"), Promise.reject("b")];

Promise.all(promises.map(function(p, index) 
  return p.then(function(data) 
    console.log("inside .map()", data, "index", index)
    return data
  , function(err) 
    console.log(err);

    // RE-THROW!!
    throw err;                  

  )
))
.then(...

如果拒绝处理程序的目的仅仅是记录,那么您可以将其移出链:

Promise.all(promises.map(function(p, index) 

  // MOVE ERROR HANDLER OUTSIDE OF CHAIN
  p.catch(function(e)  console.log(e); );

  return p.then(function(data) 
    console.log("inside .map()", data, "index", index)
    return data
  )
))
.then(...

【讨论】:

我谈到了这一点,但把它删掉了。感谢您的措辞比我做得更好:D【参考方案2】:

你在这里真正做的是这样的:

https://jsfiddle.net/9gprLc7q/5/

var notRejectedPromise = 
    Promise.reject("b")
      .then((resolved) => resolved, (err) => err)

var promises = [Promise.resolve("a"), notRejectedPromise];

Promise.all(promises)
.then(function(complete) 
  console.log("all promises after .map()", complete)
, function(err) 
  console.log("err", err)
)

但是决定通过返回任何 err 来处理错误部分,您返回了一个字符串。这不是拒绝的理由。

要真正导致Promise.all() 拒绝,您需要在.thenresolvedrejected 部分发生错误

鉴于此,如果您返回一个被拒绝的承诺,它将拒绝:

https://jsfiddle.net/9gprLc7q/3/

console.log(err)

return Promise.reject(err)

您也可以抛出错误:https://jsfiddle.net/9gprLc7q/2/

console.log(err)

throw new Error(err)

【讨论】:

为什么在.map() 删除.then() 会返回预期结果jsfiddle.net/9gprLc7q/4?为什么被拒绝的Promise 转换为已解决的Promise @guest271314 这是因为您从未将.then 附加到被拒绝的承诺上。所以现在不是返回"b",这不是拒绝,而是返回自己Promise.reject("b"),这是一个拒绝的值。 @guest271314 也许这会帮助jsfiddle.net/9gprLc7q/5。当您在原始代码中执行 return err 时,错误部分返回一个字符串而不是 Promise.reject 仅使用 throw err jsfiddle.net/9gprLc7q/6 返回预期结果,不使用 new Error(err) @guest271314 你去***.com/questions/9156176/…:D

以上是关于为啥在 Promise.all() 之后不调用 onRejected,其中包含在数组中的 Promise.reject() 传递给 Promise.all()?的主要内容,如果未能解决你的问题,请参考以下文章

与 Promise.all() 中的解析相比,为啥在 while 循环中单独解析 Promise 数组时解析更慢? [复制]

React Native 为啥我的代码在完成任务之前执行? Promise.all().then() 异步问题

为啥即使我 .catch() Promise.all() 也会抛出异常?

在 forEach 之后使用 Promise.all() 渲染 NodeJS 页面之前等待 Firebase 数据加载

promise.all 解说

如何将 Promise.all() 限制为每秒 5 个 Promise?