发送响应后继续执行(Cloudbase for Firebase)

时间:2018-04-10 06:37:56

标签: firebase google-cloud-functions

我使用带有https触发器的Firebase功能,我想知道在向客户端发送响应多长时间后,这些功能一直在执行。我想向客户端发送响应,然后执行另一个操作(发送邮件)。 目前我这样做如下:

module.exports.doSomeJob = functions.https.onRequest((req, res) => {
    doSomeAsyncJob()
    .then(() => {
        res.send("Ok");
    })
    .then(() => {
        emailSender.sendEmail();
    })
    .catch(...);
});

上面的代码对我有用,但是我怀疑代码是有效的,因为在res.send完成之前发送邮件已经完成了,所以我想知道终止进程到底是如何工作的确保代码不会破坏。

3 个答案:

答案 0 :(得分:8)

您应该期望HTTP函数在您发送响应后终止。任何其他行为都是运气或竞争条件的某种组合。不要编写依赖运气的代码。

如果您需要在工作完成之前向客户端发送响应,则需要启动第二个功能以继续HTTP功能停止的位置。使用pub / sub函数来执行此操作很常见。让HTTP函数向另一个函数发送发布/订阅消息,然后仅在发送消息后终止HTTP函数(通过发送响应)。

答案 1 :(得分:2)

如果预期的响应与执行结果不挂钩,则可以使用

module.exports.doSomeJob = functions.https.onRequest((req, res) => {
res.write('SUCCESS')
return doSomeAsyncJob()
.then(() => {
    emailSender.sendEmail();
})
.then(() => {
    res.end();
})
.catch(...);
});

这会在收到请求后立即将响应发送回去,但会保持函数运行直到调用res.end() 您的客户端可以在收到响应后立即终止连接,但是云功能将继续在后台运行 不确定这是否有帮助,但是考虑到执行pub / sub本身需要一些额外的处理并花费一些时间来执行,这可能是一种解决方法,即客户端需要在非常有限的时间内做出响应

答案 2 :(得分:1)

TL; DR

虽然https函数将在res.send()之后不久终止,但不能保证将执行res.send()之后的0行代码。

我认为更完整的答案包括两个部分:

  1. 如Doug所指出的,请勿在{{1​​}}之后放置您希望执行的任何其他代码
  2. cloud函数将在res.send()之后不久终止,但是不要指望将执行精确的0行代码

我遇到了这样的情况:对于一个数据库维护脚本,如果没有记录符合我的标准,我就与res.send()说再见,并在此之后附加逻辑。我原以为已经终止了请求,所以我希望那一部分不会运行。

产生意外结果的示例:

res.send()

在上面的示例中,我期望exports.someFunction = functions.https.onRequest((req, res) => { if (exitCriteria === true) { // we can exit the function, nothing to do console.log('Exit criteria met') res.status(200).send() } // code to handle if someCriteria was falsy console.log('Exit criteria not met, continue executing code') }) 立即终止该功能-并非如此,第二个console.log也可能会命中-以及您可能拥有的任何其他代码。但是,这不能保证,因此执行可能会在某个时刻突然停止。

产生正确结果的示例:

res.send()

在此版本中,您将恰好看到1行console.logs-就像我最初打算的那样。