首页 > 解决方案 > 已完成的 firebase 函数中的异步调用会发生什么?

问题描述

如果我选择不在 firebase 函数内等待异步调用完成,那么当函数完成时异步调用会发生什么情况?它在哪个线程上继续,它是否仍然在函数的 runtimeOpts 中运行,这对使用有何影响?

import * as firebase from 'firebase';
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

exports.action = functions.https.onRequest((req, res) => {
    admin.database().ref('action').add({ 1: 2 });
    res.end(); // or just `return;` for other functions
});

或者甚至可能

exports.action2 = functions.https.onRequest((req, res) => {
    new Promise(resolve => setTimeout(() => admin.database().ref('action').add({ 1: 2 })}, 10_000));
    res.end();
});

标签: firebasegoogle-cloud-functions

解决方案


查看 Cloud Functions 文档的这一部分,它解释了为什么“管理函数的生命周期以确保其正确解析很重要”。

如果您想确保“在您的 CF 成功达到其终止条件或状态之前,运行您的 Cloud Function (CF) 的 Cloud Functions 实例不会关闭”(在您的情况下,当异步工作完成时),您需要“通过返回一个 JavaScript 承诺来解决你的 CF”。

因此,如果您不这样做,运行您的 CF 的 Cloud Functions 实例可能会在您对一个或多个异步函数的调用完成之前关闭。

然而,这并不意味着将永远发生res.end();在您将响应发送回客户端(带有)导致异步工作完成后,运行 CF 的 Cloud Functions 实例很可能会继续运行。

问题是这完全不受您的控制(这取决于 Cloud Functions 平台如何管理您的 Cloud Function 实例):有时它可能会继续运行(完成异步工作),有时可能不会。

您会在 Stack Overflow 上的 Cloud Functions 上找到很多问题,这些问题解释了他们的问题是 Cloud Function 有时会正确执行异步工作,有时则不能:原因很简单,因为它们没有返回异步调用返回的 Promises .

这会影响使用吗?

是的,正如文档中明确指出的那样:“通过正确终止函数,您可以避免运行时间过长或无限循环的函数产生过多费用。”


因此,具体而言,在您的情况下,您应该执行以下操作:

exports.action = functions.https.onRequest(async (req, res) => {  //  <-- Note the async keyword here
    await admin.database().ref('action').add({ 1: 2 });
    res.end(); // or just `return;` for other functions
});

请注意,如果您的云函数是同步的(它不调用任何异步方法),您必须使用简单的return;语句(或通过调用send()redirect()end()HTTPS 云函数)终止它。例如:

exports.action = functions.https.onRequest((req, res) => {
    const result = 1 + 3;
    res.status(200).send(result);
});

或者

exports.unusefulCloudFunction = functions.firestore
  .document('users/{userId}').onWrite((change, context) => {
    const result = 1 + 3;
    console.log(result);
    return;
  });

推荐阅读