我很难用javascript/Nodejs8 8 Google函数将有效负载发布到Google PubSub。
因此,我有一个由HTTP请求触发的云函数,然后将请求体发布到一个pubsub (配置为拉模式)。
这是我的代码:
const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();
const topic = pubsub.topic('my-fancy-topic');
function formatPubSubMessage(reqObj){
// the body is pure text
return Buffer.from(reqObj.body);
};
exports.entryPoint = function validate(req, res) {
topic.publish(formatPubSubMessage(req)).then((messageId) => {
console.log("sent pubsub message with id :: " + messageId)
});
res.status(200).json({"res":"OK"});
};我的问题是,云函数在发布pubsub消息之前完成了执行(在日志中,日志中的“函数执行采取了X ms,以状态代码结束: 200”显示在我的青春期日志之前大约30秒或40秒。我也有好几次日志,“忽略已完成函数的异常”,而我没有得到我的pubsub )。
我不是javascript或nodejs专家,我也不掌握javascript的承诺,但我想知道是否可以使发布同步。我也在想我可能做错了什么!
提前谢谢你的帮助。
发布于 2019-10-09 14:20:27
在您的逻辑中,当HTTP消息到达时将调用回调/事件处理程序函数。然后执行发布()函数。执行发布是一个异步活动。这意味着需要一些时间才能完成发布,而且由于JavaScript (本质上)不想阻塞,因此它立即返回,您可以使用该承诺在异步工作完成后得到通知。在执行发布()之后,您的逻辑立即执行res.status(.)它向HTTP请求发送响应,这确实是来自HTTP客户端的流请求的结束。异步发布仍然在烹饪,当它本身完成时,就会发生发布的回调,并记录一个响应。
不幸的是,这不是一个很好的实践,正如谷歌这里所记录的.
https://cloud.google.com/functions/docs/bestpractices/tips#do_not_start_background_activities
在最后一个故事中,您所调用的函数validate仍将在发布完成之前结束。如果希望在执行发布()时阻塞(实际上使其同步),则可以使用JavaScript await关键字。粗略地说,有点像:
try {
let messageId = await topic.publish(....);
console.log(...);
catch(e) {
...
}您还需要将函数标记为async。例如:
exports.entryPoint = async function validate(req, res) {
...请参阅:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
您也可以简单地从函数返回一个承诺,在整个承诺得到解决之前,回调函数将不会被视为已解决。
底线是深入研究承诺。
发布于 2019-10-09 14:18:49
现在,这段代码在发布完成之前发送响应。当发送响应时,函数将终止,并且正在进行的异步工作可能无法完成。
相反,您应该只在发布完成后发送响应,这意味着将这一行代码放入then回调中。
exports.entryPoint = function validate(req, res) {
topic.publish(formatPubSubMessage(req)).then((messageId) => {
console.log("sent pubsub message with id :: " + messageId)
res.status(200).json({"res":"OK"});
});
};我建议花一些时间学习承诺是如何工作的,因为这对于构建正确工作的功能至关重要。
https://stackoverflow.com/questions/58305921
复制相似问题