我正在使用带有https触发器的Firebase函数,我想知道在向客户机发送响应之后,函数还会继续执行多久。我想向客户端发送一个响应,然后执行另一个操作(发送邮件)。目前,我正在按如下方式进行此操作:
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
doSomeAsyncJob()
.then(() => {
res.send("Ok");
})
.then(() => {
emailSender.sendEmail();
})
.catch(...);
});
上面的代码对我来说是有效的,但是我怀疑这些代码只是因为在res.send完成之前发送邮件就完成了,所以我想知道终止过程到底是如何工作的,以确保代码不会中断。
您应该期望HTTP函数在发送响应后立即终止。任何其他的行为都是运气或种族条件的某种组合。不要写靠运气的代码。
如果您需要在工作完全完成之前向客户机发送响应,则需要启动第二个函数以继续HTTP函数停止的地方。通常使用pub/sub函数来处理。让HTTP函数向另一个函数发送pub/sub消息,然后仅在消息发送后终止HTTP函数(通过发送响应)。
如果预期的响应没有与执行的结果挂钩,那么您可以使用
module.exports.doSomeJob = functions.https.onRequest((req, res) => {
res.write('SUCCESS')
return doSomeAsyncJob()
.then(() => {
emailSender.sendEmail();
})
.then(() => {
res.end();
})
.catch(...);
});
这会在收到请求后立即发送响应,但会一直运行函数,直到调用res.end()
您的客户机可以在收到响应后立即结束连接,但云函数会一直在后台运行(不确定这是否有帮助),但考虑到执行pub/sub本身需要一些额外的处理并需要时间,因此它可能是客户机在非常有限的时间内需要响应的一种解决方法
虽然https函数将在res.send()
之后不久终止,但不能保证在res.send()
之后执行0行代码。
res.send()
res.send()
之后不久终止,但不要期望将执行正好0行代码我遇到过这样一种情况:对于一个db维护脚本,如果没有记录满足我的标准,我就用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')
})
在上面的示例中,我期望res.send()
立即终止函数--事实并非如此,第二个console.log也可能被命中--连同您可能拥有的任何其他代码。但是,这并不能保证,因此执行可能会在某个时刻突然停止。
生成正确结果的示例:
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()
}
else {
// code to handle if someCriteria was falsy
console.log('Exit criteria not met, continue executing code')
}
})
在这个版本中,您将看到只有一行console.logs-正如我最初所希望的那样。