Firebase 函数如何正确处理错误

shm*_*les 4 javascript error-handling firebase google-cloud-functions

注意:这个问题主要是关于错误处理,如果这是一个好的方法,而不是关于嵌套承诺,请在关闭前阅读

由于目前没有诸如 firestore 和 firebase 数据库之类的服务的错误代码,我正在使用一个系统来了解函数在哪里失败并相应地处理错误,简化版本如下:

exports.doStuff = functions.https.onCall((data, context) => {

    return [promise doing stuff goes here].catch(error => { throw new Error('ERROR0') })
        .then(result => {
            return [promise doing stuff goes here, needs result of previous promise]
                .catch(error => { throw new Error('ERROR1') })
        })
        .then(result => {
            return [promise doing stuff goes here, needs result of previous promise]
                .catch(error => { throw new Error('ERROR2') })
        })
        .then(result => {
            //inform client function successful
            return {
                success: true
            }
        })
        .catch(error => {
            if (error !== null) {
                switch (error.message) {
                    case 'ERROR0':
                        //do stuff
                        throw new functions.https.HttpsError('unknown', 'ERROR0');
                    case 'ERROR1':
                        //do stuff
                        throw new functions.https.HttpsError('unknown', 'ERROR1');
                    case 'ERROR2':
                        //do stuff
                        throw new functions.https.HttpsError('unknown', 'ERROR2');
                    default:
                        console.error('uncaught error: ', error);
                        throw error;
                }
            }
        });
});
Run Code Online (Sandbox Code Playgroud)

问题是,对于每个.catch()返回的承诺中的每个,我收到以下警告:warning Avoid nesting promises

所以我的问题是,有没有更好的方法来处理错误?

sam*_*man 7

归根结底,这是一种风格建议,以防止出现奇怪且难以识别的错误。大多数情况下,重写可以消除警告。例如,您可以按如下方式重写代码,同时保留相同的功能。

exports.doStuff = functions.https.onCall(async (data, context) => {

    const result1 = await [promise doing stuff goes here]
      .catch(error => {
          throw new functions.https.HttpsError('unknown', 'ERROR0', { message: error.message } )
      });

    const result2 = await [promise based on result1 goes here]
      .catch(error => {
          throw new functions.https.HttpsError('unknown', 'ERROR1', { message: error.message } )
      });

    const result3 = await [promise based on result1/result2 goes here]
      .catch(error => {
          throw new functions.https.HttpsError('unknown', 'ERROR2', { message: error.message } )
      });

    return {
      success: true
    };
});
Run Code Online (Sandbox Code Playgroud)

最后,不是在unknown任何地方使用,您可以使用第一个参数几个可能值之一,同时将您需要的任何支持信息作为第三个参数传递(如上图所示,我通过原始错误消息)。