I have a conceptual question concerning async await code : this is a snippet I have in my code:
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
}
Now if the line
await file.save()
(that is happening on a promise success) fails, then my app throws a Unhandled promise rejection and this exactly is my issue.
Also if the passed accept method throws an exception, the promise will have an unhandled rejection.
I could naturally surround the code in the else statement with a try catch block, but that won't help, worse, it will mislead the developer since he will think the error comes from the promise code s3.upload, while that part will have succeeded and the accept code will be the one that failed : which has definitely different consequences :
- a s3 upload failure means the file didn't upload
- but a file.save() failure means only the file status in our db was not updated, but the physical file is in the s3 system
those two errors cannot be handled in the same try catch block, but catching what happens in the accept method is also not clear (about what happened behind the scene). Finally, adding try catch blocks in callback-promise bridges complexifies the code and readability
So what are the best practices in this case