首页 > 解决方案 > 在另一个 Promise 的回调中捕获 Promise 错误

问题描述

下面的代码按预期运行。如果调用了收费函数,则该函数从中获取相关票证对象firestore,然后将其返回给客户端。

如果票证不存在,该函数会抛出一条HttpsError错误消息,该消息将由客户端解析。

exports.charge = functions.https.onCall(data => {
  return admin.firestore().collection('tickets').doc(data.ticketId.toString()).get()
    .then((snapshot) => {
      return { ticket: snapshot.data() }
    })
    .catch((err) => {
      throw new functions.https.HttpsError(
        'not-found', // code
        'The ticket wasn\'t found in the database'
      );
    });
  });

问题出现在这之后。我现在需要使用 Stripe 向用户收费,这是另一个异步进程,将返回一个Promise. 收费需要第一个异步方法获取的定价信息,因此需要在snapshot检索到后调用。

exports.charge = functions.https.onCall(data => {
  return admin.firestore().collection('tickets').doc(data.ticketId.toString()).get()
    .then((snapshot) => {
      return stripe.charges.create(charge) // have removed this variable as irrelevant for question
        .then(() => {
          return { success: true };
        })
        .catch(() => {
          throw new functions.https.HttpsError(
            'aborted', // code
            'The charge failed'
          );
        })
    })
    .catch(() => {
      throw new functions.https.HttpsError(
        'not-found', // code
        'The ticket wasn\'t found in the database'
      );
    });
  });

我的问题是在新charge请求中捕获错误。似乎如果收费失败,它会成功调用第一个“中止”捕获,但随后将其传递给父捕获,并且错误被覆盖并且应用程序看到“未找到票证”错误。

我怎样才能阻止这种情况发生?我需要分别捕获这两个错误并HttpsError为每个错误抛出一个。

标签: javascriptnode.jsfirebasepromisegoogle-cloud-functions

解决方案


status通常,可以通过添加节点然后与最终then块链接来处理此类问题。您可以尝试以下操作

exports.charge = functions.https.onCall(data => {
  return admin.firestore().collection('tickets').doc(data.ticketId.toString()).get()
    .then((snapshot) => {
      return stripe.charges.create(charge)
        .then(() => {
          return { success: true };
        })
        .catch(() => {
             return {
                status : 'error', 
                error : new functions.https.HttpsError(
            'aborted', // code
            'The charge failed',
            { message: 'There was a problem trying to charge your card. You have NOT been charged.' }
          )};
        })
    })
    .catch(() => {
      return {
         status : 'error',
         error : new functions.https.HttpsError(
        'not-found', // code
        'The ticket wasn\'t found in the database',
        { message: 'There was a problem finding that ticket in our database. Please contact support if this problem persists. You have NOT been charged.' }
      )};
    }).then((response) => {
         if(response.status === 'error') throw response.error;
         else return response;
    });
  });

推荐阅读