【问题标题】:Promise.all getting Unhandled rejectionPromise.all 得到未处理的拒绝
【发布时间】:2019-10-13 15:10:36
【问题描述】:

我正在使用 Promise.all 并捕获错误,但仍然收到未处理的拒绝

const Promise = require('bluebird');

function sleep(milis) {
return new Promise(function(resolve, reject) {
    if (milis == 1000) {
        console.log('Rejecting millis', milis)
        setTimeout(() => {
            reject('Got error')
        }, milis);

    } else {
        console.log('Processing millis', milis)
        setTimeout(() => {
            resolve(milis);
        }, milis);

    }
});
}

function test() {

try {
    let lists = [2000, 1000, 3000]
    Promise.all(
            lists.map(record => {
                try {
                    sleep(record)
                } catch (err) {
                    console.log('Error inside catch block1', err)
                    throw err
                }
            })
        ).then(data => {
            console.log('Resolved', data)
        })
        .catch(err => {
            console.log('Error inside catch block2', err)
            throw err

        });

} catch (err) {
    console.log('Error inside catch block3', err)
}
}


test();

使用 catch 块后为什么仍然会收到未处理的拒绝。任何帮助表示赞赏。但是如果我使用异步等待不会得到未处理的拒绝。

【问题讨论】:

  • try-catch 块不会捕获承诺拒绝,除非您使用 async-await

标签: node.js ecmascript-6 promise es6-promise bluebird


【解决方案1】:

您的代码存在多个问题,让我们一一解决:

首先

当您映射 lists 数组时,您永远不会返回您从 sleep() 函数获得的承诺。这意味着您提供给Promise.all() 的是一个用undefined 填充的数组。 Promise.all() 将不是承诺的值视为已解决的承诺,因此无论sleep() 创建的承诺是解决还是拒绝,您的Promise.all() 将始终解决。这也意味着没有任何东西可以捕获来自 sleep() 的拒绝承诺,这就是为什么您的脚本当前会收到未处理的承诺拒绝。
您可以通过使用return sleep(record) 正确返回承诺来解决此问题。但这不足以摆脱所有未处理的承诺拒绝,所以让我们继续......

其次

您已将对sleep() 的调用封装在try-catch 块中。除非您使用async-await,否则try-catch 块将不会捕获被拒绝的承诺。在这种情况下,它只会捕获创建 Promise 时抛出的错误。如果这是你的意图,那很好,但如果你的意图是捕捉被拒绝的承诺,那它就行不通了。

第三

您已将catch() 处理程序附加到您的Promise.all()。与前面提到的try-catch 不同,它实际上负责处理任何被拒绝的承诺。但是,您在此处理程序中重新抛出错误,这意味着承诺链仍将被拒绝。您已将您的 Promise.all() 包装在另一个 try-catch 块中,但如前所述,这不会捕获被拒绝的承诺,因此仍然被拒绝的承诺最终将未被处理。
在这种情况下,您根本不应该在上一个 catch() 处理程序中重新抛出错误,因为我在这里看不到这样做的任何意义。如果您出于某种原因需要重新抛出它,您需要稍后在链中添加另一个 catch() 处理程序。

【讨论】:

    【解决方案2】:

    原因是您没有处理此sleep 方法的错误。 它应该是这样的。

    function sleep(milis) {
    return new Promise(function (resolve, reject) {
        if (milis == 1000) {
            console.log('Rejecting millis', milis)
            setTimeout(() => {
                reject('Got error')
            }, milis);
    
        } else {
            console.log('Processing millis', milis)
            setTimeout(() => {
                resolve(milis);
            }, milis);
    
        }
     }).catch(error => {
        console.log(error);
     })
    }
    

    【讨论】:

      【解决方案3】:

      TL;DR:throw err 内的 .catch 处理程序不会被代码中的任何其他 catch 捕获,因此您会收到未处理的承诺拒绝。

      首先,在这段代码中sn-p

      lists.map(record => {
        try {
          sleep(record)
        } catch (err) {
          console.log('Error inside catch block1', err)
          throw err
        }
      })
      

      .map 的结果将是[undefined, undefined, undefined],因为该函数不返回任何值。如果您希望它为每个列表元素返回一个承诺,则需要编写 return sleep(record)

      然后,请注意主catch 块在Promise.all.then/.catch 处理程序之前执行。如果您在主catch 块之后添加console.log ,您会看到它。这意味着您在 .catch 处理程序中重新抛出的异常不会被任何东西捕获,并且显示为未处理。

      【讨论】:

      • 如何解决上述代码的未处理拒绝
      猜你喜欢
      • 2020-12-27
      • 1970-01-01
      • 2019-03-15
      • 2016-07-21
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 2018-01-18
      相关资源
      最近更新 更多