return value from zmq socket

2019-07-15 15:43发布

问题:

I am using Socket.IO to have a client webpage fetch data dynamically from my Node.JS server. On the server-side, I am forwarding the request to a Python backend using the zeromq socket library (REQ/REP structure, see the rrclient.js example from zguide).

However, since my server is acting as the socket.io server, I have to wrap my response as follows in order to send it back to the specific client:

socket.on('app_request',function(appRequest){
      //route this request to the backend.
      var results = fetch_data(appRequest);
      //return it to the client
      socket.emit('app_results',results);
  });

so the fetch_data function uses a zmq socket (socket.send) to push a request to the server.

But the Node ZMQ socket responds to request using a socket.on('message',function(){}); listener and doesn't actually return anything.

How can I use socket.on('message',function(){}); to return a value to the specific function that initiated a socket.send() request?

In other words, how can I get a client's socket.io request to have Node.JS fetch relevant data from a python backend using ZMQ, then return it back to the socket.io client? (in a non-blocking fashion of course)

回答1:

I've done something similar, you'll want to rework it like so;

socket.on('app_request',function(appRequest){
  //route this request to the backend.
  fetch_data(appRequest, function(err, results) {
       socket.emit('app_results',results);
  });
});

zmq is non-blocking so the response is not received before your sending it down to socket.io, using this method you can adjust your fetch_data method to store the callback until the response is returned and then fire it.

Rough fetch_data for inspiration only not tested;

var zmq = require('zmq'),
    req = zmq.socket('req'),
    count = 0,
    jobs = {};


req.on('message', function(response) {
    var args  = JSON.parse(response),
        reply = args[0],
        id    = args[i];

    if (id && jobs[id]) {
         jobs[id].apply(null, Array.isArray(reply) ? reply : [reply]);

         delete jobs[id];
    }
}

function fetch_data(appRequest, callback) {
    var data = JSON.stringify([appRequest, count]);

    jobs[count] = callback;

    req.send(data);

    ++count;
}

Then on the other side parse the json and keep the id and send it back with the response.