我正在使用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块后,为什么仍会出现Unhandled拒绝。任何帮助表示赞赏。但是,如果我使用异步等待,则不会收到未处理的拒绝。
答案 0 :(得分:1)
TL; DR:throw err
处理程序中的.catch
不会被代码中的其他catch
捕获,因此您会遇到未处理的承诺拒绝。
首先,在此代码段中
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
块是在.then
的{{1}} / .catch
处理程序之前执行的。如果在主要Promise.all
主块之后添加console.log
,则会看到它。这意味着您在catch
处理程序中重新抛出的异常不会被任何东西捕获,并显示为未处理。
答案 1 :(得分:1)
原因是您没有在此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);
})
}
答案 2 :(得分:1)
您的代码有多个问题,让我们一步一步地解决它们:
在映射lists
数组时,您永远不会返回从sleep()
函数获得的承诺。这意味着您提供给Promise.all()
的是一个由undefined
填充的数组。 Promise.all()
将非承诺的值视为已解决的承诺,因此,无论Promise.all()
创建的承诺是解决还是拒绝,您的sleep()
都会始终解析。这也意味着没有任何东西能够捕捉到sleep()
拒绝的诺言,这就是为什么您的脚本当前无法处理诺言的原因。
您可以通过使用return sleep(record)
正确返回承诺来解决此问题。但这还不足以消除所有未处理的诺言拒绝,因此让我们继续...
您已将对sleep()
的呼叫包装在try-catch
块中。除非您使用async-await
,否则try-catch
阻止将不捕获被拒绝的承诺。在这种情况下,它将仅捕获创建诺言时引发的错误。如果这是您的意图,那很好,但是如果您的意图是兑现被拒绝的承诺,那将是行不通的。
您已将catch()
处理程序附加到Promise.all()
。与前面提到的try-catch
不同,实际上它处理了所有被拒绝的承诺。但是,您在该处理程序中重新抛出了错误,这意味着承诺链仍将被拒绝。您已经将Promise.all()
包裹在另一个try-catch
块中,但是如上所述,这不能捕获已拒绝的承诺,因此仍然被拒绝的承诺最终将无法得到处理。
在这种情况下,您不应简单地在最后一个catch()
处理程序中重新抛出错误,因为我在这里看不到这样做的任何意义。如果出于任何原因需要重新抛出它,则需要在链的后面添加另一个catch()
处理程序。