【发布时间】:2023-03-14 15:47:02
【问题描述】:
在我编写的一些 Node.js 脚本中,我注意到即使最后一行是同步调用,有时它也不会在 Node.js 退出之前完成。
我从未见过console.log 语句在退出前无法运行/完成,但我看到其他一些语句在退出前无法完成,我相信它们都是同步的。我可以理解为什么在这种情况下异步函数的回调当然会失败。
有问题的代码是一个 ZeroMQ .send() 调用,如下所示:
var zmq = require('zmq');
var pub = zmq.socket('pub');
pub.bindSync('tcp://127.0.0.1:5555');
setInterval(function(){
pub.send('polyglot');
},500);
上面的代码按预期工作......但如果我删除 setInterval() 并像这样调用它:
var zmq = require('zmq');
var pub = zmq.socket('pub');
pub.bindSync('tcp://127.0.0.1:5555');
pub.send('polyglot'); //this message does not get delivered before exit
process.exit(0);
...那么消息将不会被传递 - 程序显然会在 pub.send() 调用完成之前退出。
在退出 Node.js 之前确保语句完成的最佳方法是什么?关闭挂钩在这里可以工作,但我担心这只会掩盖问题,因为您无法将确保运行所需的所有内容都放在关闭挂钩中。
这个问题也可以这样证明:
if (typeof messageHandler[nameOfHandlerFunction] == 'function') {
reply.send('Success');
messageHandler[nameOfHandlerFunction](null, args);
} else {
reply.send('Failure'); //***this call might not complete before the error is thrown below.***
throw new Error('SmartConnect error: no handler for ZMQ message sent from Redis CSV uploader.');
}
我认为这是一个合法/严重的问题,因为很多程序只需要发布消息然后死掉,但是我们如何才能有效地确保所有消息都被发送(尽管不一定接收)?
编辑: 解决此问题的一种(潜在)方法是:
socket.send('xyz');
socket.close(); // supposedly this will block until the above message is sent
process.exit(0);
【问题讨论】:
-
按照设计,除非 process.exit() 被调用,否则同步脚本将运行到完成,因此在这种情况下您将不得不显示一些代码。否则,这只是对某些甚至可能不是真的事情的猜测。
-
您不能保证关闭挂钩中的异步完成。
-
可以尝试用 0 将其包装在 setTimeout 中吗?
-
我添加了有问题的代码,请告诉我你的想法
-
你为什么打电话给
process.exit(0)?如果节点进程完成(关闭连接、停止侦听等),它将终止。此外,几乎所有在节点中执行 I/O 的操作都是异步的。不接受回调并不意味着它是同步的——它只是意味着你无法知道它何时完成。
标签: javascript node.js zeromq