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 函数,因为从链接回调(thencatchfinally)返回承诺会同时解决和拒绝正确传播。

即使cleanup功能失效,也不会造成任何问题;拒绝将传播到最外层(返回的)承诺,并且调用者代码可以以与 promise1promise2promise3 函数失败相同的方式捕获它。