Javascript - 在 catch 块中处理承诺
Javascript - Handle promises within catch block
我正在用一个 catch 块处理链式承诺。
如果其中一个承诺被拒绝,我想根据失败的步骤在 catch 块中进行清理。
但是,清理本身也是 returns 一个 Promise,需要在我最终拒绝该函数之前完成它。
问题是:
如果我的清理承诺没有解决怎么办?这不会导致 .then & .catch 的循环吗?如何确保我的清理在结束函数之前执行?
示例:
return promise1()
.then(() => promise2)
.then(() => promise3)
.then(() => {
return { result: xyz }
}
.catch((error) => {
return cleanup()
.then(() => {
throw(error)
}
}
就我个人而言,我只会使用 async
/ await
语法。这允许更简单地控制等待和解析/拒绝值。
const myAsyncFun = async () => {
try {
await promise1()
await promise2
await promise3
return { result: "xyz" }
}
catch (error) {
try {
await cleanup()
}
catch (cleanupError) {
// handle cleanup error
}
finally {
throw error // reject with the original error
}
}
}
下面是原来的回答...
听起来你想使用 Promise.prototype.finally()
When the promise is settled, i.e either fulfilled or rejected, the specified callback function is executed
.catch(error =>
cleanup()
.catch(cleanupErr => {
// handle cleanup error here
})
.finally(() => Promise.reject(error))
)
这将确保结果是被拒绝的承诺(使用 error
拒绝),无论 cleanup()
是否解决。
演示
const cleanup = (fail) =>
!fail ? Promise.resolve("cleanup good") : Promise.reject("cleanup bad")
const go = (failMain, failCleanup) => {
const p = !failMain
? Promise.resolve("main good")
: Promise.reject("main bad")
return p.then(() => ({ result: "xyz" }))
.catch(error =>
cleanup(failCleanup)
.catch(cleanupErr => {
// handle cleanup error here
console.warn(cleanupErr)
})
.finally(() => Promise.reject(error))
)
}
(async () => {
console.info("No errors")
await go(false, false).then(console.log, console.error)
console.info("Main error only")
await go(true, false).then(console.log, console.error)
console.info("Main and cleanup errors")
await go(true, true).then(console.log, console.error)
})()
第一个问题:没有!一旦你的程序在catch块中,它就和里面的promises没有任何关系,所以它不会catch cleanup().
关于你的第二个问题:你当然可以为它编写另一个 catch 块并抛出一个错误并显示相关的错误消息(例如“无法执行清理”)
一切顺利。
您当前的代码将正确地等待 cleanup
函数,因为从链接回调(then
、catch
、finally
)返回承诺会同时解决和拒绝正确传播。
即使cleanup
功能失效,也不会造成任何问题;拒绝将传播到最外层(返回的)承诺,并且调用者代码可以以与 promise1
、promise2
或 promise3
函数失败相同的方式捕获它。
我正在用一个 catch 块处理链式承诺。
如果其中一个承诺被拒绝,我想根据失败的步骤在 catch 块中进行清理。
但是,清理本身也是 returns 一个 Promise,需要在我最终拒绝该函数之前完成它。
问题是: 如果我的清理承诺没有解决怎么办?这不会导致 .then & .catch 的循环吗?如何确保我的清理在结束函数之前执行?
示例:
return promise1()
.then(() => promise2)
.then(() => promise3)
.then(() => {
return { result: xyz }
}
.catch((error) => {
return cleanup()
.then(() => {
throw(error)
}
}
就我个人而言,我只会使用 async
/ await
语法。这允许更简单地控制等待和解析/拒绝值。
const myAsyncFun = async () => {
try {
await promise1()
await promise2
await promise3
return { result: "xyz" }
}
catch (error) {
try {
await cleanup()
}
catch (cleanupError) {
// handle cleanup error
}
finally {
throw error // reject with the original error
}
}
}
下面是原来的回答...
听起来你想使用 Promise.prototype.finally()
When the promise is settled, i.e either fulfilled or rejected, the specified callback function is executed
.catch(error =>
cleanup()
.catch(cleanupErr => {
// handle cleanup error here
})
.finally(() => Promise.reject(error))
)
这将确保结果是被拒绝的承诺(使用 error
拒绝),无论 cleanup()
是否解决。
演示
const cleanup = (fail) =>
!fail ? Promise.resolve("cleanup good") : Promise.reject("cleanup bad")
const go = (failMain, failCleanup) => {
const p = !failMain
? Promise.resolve("main good")
: Promise.reject("main bad")
return p.then(() => ({ result: "xyz" }))
.catch(error =>
cleanup(failCleanup)
.catch(cleanupErr => {
// handle cleanup error here
console.warn(cleanupErr)
})
.finally(() => Promise.reject(error))
)
}
(async () => {
console.info("No errors")
await go(false, false).then(console.log, console.error)
console.info("Main error only")
await go(true, false).then(console.log, console.error)
console.info("Main and cleanup errors")
await go(true, true).then(console.log, console.error)
})()
第一个问题:没有!一旦你的程序在catch块中,它就和里面的promises没有任何关系,所以它不会catch cleanup().
关于你的第二个问题:你当然可以为它编写另一个 catch 块并抛出一个错误并显示相关的错误消息(例如“无法执行清理”)
一切顺利。
您当前的代码将正确地等待 cleanup
函数,因为从链接回调(then
、catch
、finally
)返回承诺会同时解决和拒绝正确传播。
即使cleanup
功能失效,也不会造成任何问题;拒绝将传播到最外层(返回的)承诺,并且调用者代码可以以与 promise1
、promise2
或 promise3
函数失败相同的方式捕获它。