打破承诺链并抛出异常

时间:2018-10-31 19:24:33

标签: javascript node.js firebase google-cloud-functions

当前,如果asyncFunction1()的promise回调中捕获了错误,则该应用将正确引发“问题A”异常。但是,这是通过承诺链传递的,应用最终会看到“问题B”,这意味着该应用向用户显示了错误的错误。

我实际上需要中止执行并打破链条,同时抛出相关错误。我该怎么办?

可以在以下位置找到HttpsError类信息:https://firebase.google.com/docs/reference/functions/functions.https.HttpsError

它明确提到:

  

确保在函数的顶层抛出此异常   而不是从回调内部进行,因为这不一定会终止   具有此异常的功能。

我似乎已经陷入了陷阱,但不知道如何解决它。如果有人可以帮助我重构代码,以便我可以有效地捕获并正确处理这些错误,将不胜感激。

exports.charge = functions.https.onCall(data => {
  asyncFunction1()
    .then(() => {
      asyncFunction2();
    })
    .catch((err) => {
      throw new functions.https.HttpsError(
        'not-found',
        'Problem A'
      );
    })
    .then(() => {
      asyncFunction3();
    })
    .catch((err) => {
      throw new functions.https.HttpsError(
        'not-found',
        'Problem B'
      );
    })
});

2 个答案:

答案 0 :(得分:2)

有多种方法可以解决此问题:

  1. 您可以让每个异步功能仅在拒绝时设置适当的错误,因此您不必在自己的.catch()中手动添加正确的错误。

  2. 您可以在最后一个.catch()中进行测试,以查看是否已经设置了适当的错误,如果已设置则将其重新抛出,而不是用另一个错误覆盖它。

  3. 您可以直接将最后一个.catch()放在asyncFunction3()调用上,而不是像这样在整个链上放置,因此您只针对具有该错误代码的该函数拒绝: / p>

修改后的代码:

exports.charge = functions.https.onCall(data => {
    return asyncFunction1().then(() => {
        return asyncFunction2();
    }).catch((err) => {
        // set appropriate error for rejection in either of the first two async functions
        throw new functions.https.HttpsError('not-found', 'Problem A');
    }).then(() => {
        return asyncFunction3().catch((err) => {
            // set appropriate error for rejection in asyncFunction3
            throw new functions.https.HttpsError('not-found', 'Problem B');
        });
    });      
});

注意:我还添加了几个return语句,以确保将promises链接到链中并从导出的函数返回。而且,我浓缩了使其更易于阅读的逻辑。


异步/等待也可能是这种情况(尽管我不确定functions.https.onCall()是否允许这样做)

exports.charge = functions.https.onCall(async (data) => {
    try {
        await asyncFunction1()
        await asyncFunction2();
    } catch(e) {
        throw new functions.https.HttpsError('not-found', 'Problem A');
    }
    try {
        await asyncFunction3();
    } catch(e) {
        throw new functions.https.HttpsError('not-found', 'Problem B');
    }
});

答案 1 :(得分:0)

这样的作品行吗?

exports.charge = functions.https.onCall(data => {
   return Promise.resolve().then(
      () => {
          return asyncFunction1();
      }).then(
      () => {
          return asyncFunction2();
      }).then(
      () => {
          return asyncFunction3();
      }).catch(
      err => {
          throw new functions.https.HttpsError(err);
      });
}