Node.js socket.send()函数在退出之前无法完成

时间:2015-04-27 21:52:01

标签: javascript node.js zeromq

在我编写的一些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);

2 个答案:

答案 0 :(得分:8)

潜入equals(Object),您可以看到Socket.send只有zeromq.node

this._outgoing.push([msg, flags]);

...然后pushes your data to _outgoing

this._flush();

看起来像calls _flush iff zmq.ZMQ_SNDMORE is unset。如果_flush()失败,请_flush is actually doing the socket write

<强> 编辑:

我猜测在退出前调用pub.unbind()会强制调用_flush()

pub.unbind('tcp://127.0.0.1:5555', function(err) {
  if (err) console.log(err);
  process.exit(0); // Probably not even needed
});

答案 1 :(得分:0)

我认为简单的答案是socket.send()方法实际上是异步,这就是为什么我们看到我在OP中描述的行为。

那么问题是 - 为什么socket.send()必须是异步的 - 是否可能没有阻塞/同步版本,我们可以将其用于OP中的目的?我们可以请socket.sendSync()吗?