首页 > 解决方案 > 条件承诺链

问题描述

我正在寻找将一些承诺链接在一起的代码。我有一个条件,基于一个承诺的结果,我要么调用返回承诺的下一个函数并继续链接其他几个函数,要么我什么都不做(有效地结束承诺链)。

我有以下三种可能的解决方案,但我觉得它们都有点混乱。

这是我的第一种方法,我不喜欢这里的嵌套承诺。

initalAsyncCall()
  .then((shouldContinue) => {
    if (shouldContinue) {
      return nextStep()
        .then(() => anotherStep())
    }
  })
  .catch((error) => {
    handleError(error);
  })

这是我的第二个。这个似乎有点长,可能更难阅读

const shouldContinuePromise = initialAsyncCall();
const nextStepPromise = shouldContinuePromise.then((shouldContinue) => {
  if (shouldContinue) return nextStep();
});
Promise.all([shouldContinuePromise, nextStepPromise])
  .spread((shouldContinue) => {
    if (shouldContinue) return anotherStep();
  })
  .catch((error) => {
    handleError(error);
  });

最后,这是我的最后一种方法。我在这里不喜欢的是,当它不是真正的错误时,我会抛出一个错误。

initalAsyncCall()
  .then((shouldContinue) => {
    if (!shouldContinue) throw new HaltException()
    return nextStep();
  })
  .then(() => anotherStep())
  .catch(HaltException, (ex) => {
    // do nothing... maybe some logging
  })
  .catch((error) => {
    handleError(error);
  })

标签: node.jspromisebluebird

解决方案


您的第一种方法似乎很好,为避免嵌套,您可以返回承诺并为嵌套部分添加额外的 then 块,如下所示

initalAsyncCall()
  .then((shouldContinue) => {
    if (shouldContinue) {
      return nextStep()
    } else {
      throw Error('skip next step')
    }
  })
  .then(() => anotherStep())
  .catch((error) => {
    handleError(error);
  })

如果您不喜欢在第三种方法中抛出不必要的错误,您可以使用 async/await 来获得更多控制并摆脱函数范围/嵌套问题,由于更好的错误堆栈,新的 nodejs 版本也建议使用此方法痕迹。

try {
    const shouldContinue = await initalAsyncCall()
    if (shouldContinue) {
      await nextStep()
      await anotherStep()
// or await Promise.all([nextStep(), anotherStep()]) if they're not dependent
    }
}
catch (error) {
  handleError(error);
}

推荐阅读