Google 云函数:functions.https.onCall 返回 null 但值在日志中正确显示

Google cloud functions: functions.https.onCall returning null but the value is shown correctly in the logs

我正在通过 Axios async-await 调用第三方 API,并通过 google 云函数将结果返回给 flutter 应用程序。我被迫使用 functions.https.onCall 因为据我所知 flutter 不能调用 onRequest 函数。

结果在云函数的日志 console.log 中正确显示,但是当 flutter 应用程序调用该函数时,它总是接收 null。为什么?

getSmsBalance: functions.https.onCall(async (data, context) => {
    const business_id = data.business_id;
    const collectionRef = db.collection("buser_sms");
    const snapshot = await collectionRef.where("id", "==", business_id).get();
    if (snapshot.empty) {
        console.log("No matching documents - getSMSBalance .");
        let response = {
            status: false,
        };
        return JSON.stringify(response);
    }
    snapshot.forEach((doc) => {
        if (
            doc.data().enableReservationSms == true ||
            doc.data().enableAutoReminder == true ||
            doc.data().enableReminderSms == true
        ) {
            // get balance
            (async () => {
                const balance = await getBalance(
                    doc.data().senderId,
                    doc.data().username,
                    doc.data().password
                )
                    .then((result) => {
                        let response = {
                            status: true,
                            data: result,
                        };
                        console.log("balance is " + result);
                        return JSON.stringify(response);
                    })
                    .catch((err) => {
                        console.error(`Error - getSmsBalance - ${err}`);
                        let response = {
                            status: false,
                        };
                        return JSON.stringify(response);
                    });
            })();
        }
    });
}),

您的代码存在几个问题:

  1. 您正在 Array.forEach 中使用 async/await 语法,由于其固有设计,它不允许等待。如果要在循环迭代中使用 async/await,则需要使用 Array.map 等。但在大多数情况下,您不应该在循环内使用 async/await,因为它消除了异步代码执行的优势(每次迭代仅在前一次迭代之后触发)。
  2. 除了 snapshot.empty 之外,您的函数中没有 return 任何内容。 thencatch 回调中的 return 仅将值分配给变量 balance,之后不会使用该变量。

所以总而言之,您需要使用类似的东西:

  return Promise.all(
    snapshot.map((doc) => {
      return getBalance(
        doc.data().senderId,
        doc.data().username,
        doc.data().password
      )
        .then((result) => {
          let response = {
            status: true,
            data: result,
          };
          console.log('balance is ' + result);
          return JSON.stringify(response);
        })
        .catch((err) => {
          console.error(`Error - getSmsBalance - ${err}`);
          let response = {
            status: false,
          };
          return JSON.stringify(response);
        });
    })
  );

请注意,我提供的代码是截取的,没有考虑您实际需要的输出格式。拥有一个 response 数组可能不是您所需要的。但是您最终应该能够根据您的需要调整该代码。