我有一个关于异步等待代码的概念性问题:这是我在代码中的代码片段:
async function uploadFileBackup(fileId, versionNumber, filePath, sync) {
//...some irrelevant code
const toReturn = new Promise((accept, reject) => {
s3.upload(params, async function (err, data) {
if (err) {
reject(err)
} else {
//here is the relevant code
file.backupStatus = 'success'
await file.save()
accept(data)
}
})
})
if (sync)
return toReturn
//...some other irrelevant code
}
现在如果该行
await file.save()
(在承诺成功时发生)失败,然后我的应用程序抛出未处理的承诺拒绝,这正是我的问题。
此外,如果传递的接受方法抛出异常,则承诺将处于未处理的拒绝状态。
我可以使用 try catch 块自然地围绕else语句中的代码,但这不会有帮助,更糟糕的是,它会误导开发人员,因为他会认为错误来自承诺代码 s3.upload ,而那部分将成功,接受代码将是失败的代码:具有明显不同的后果:
这两个错误无法在同一个try catch块中处理,但是捕获accept方法中发生的事情也不清楚(关于场景背后发生了什么)。最后,在回调承诺桥中添加try catch块会使代码和可读性变得复杂化
那么这种情况下的最佳做法是什么
答案 0 :(得分:3)
您需要避开Promise
constructor antipattern!并且不能将async
函数作为普通回调传递给忽略返回值的函数,因此不会处理返回的promise中的错误。
您应该单独promisify s3.upload
function upload(params) {
return new Promise((resolve, reject) => {
s3.upload(params, (err, data) => {
if (err) reject(err)
else resolve(data)
})
})
}
然后像
一样使用它async function uploadFileBackup(fileId, versionNumber, filePath, sync) {
… // some irrelevant code
if (sync) {
const result = await upload(params)
file.backupStatus = 'success'
await file.save()
return result
}
… // some other irrelevant code
}
此外,您应该避免将toReturn
创建为仅有条件等待的承诺(if (sync)
),否则forgotten about without handling errors。
如果您现在想要处理来自await upload
或await file.save
的错误,可以将其包含在try
/ catch
或whatever is appropriate中。如果你不处理它们,它们将拒绝uploadFileBackup
返回的承诺,并且需要由其来电者处理,但它们不会导致流浪承诺的未处理拒绝。