nodejs async.queue从其他方法调用回调

时间:2017-11-16 10:08:39

标签: javascript node.js sockets asynchronous async.js

是否可以从工作者函数以外的其他函数调用finish回调作业?因为我想做的是以下几点:

  1. 我收到一条推送到async.queue
  2. 的POST请求
  3. 提供给async.queue发送的工作人员功能然后通过sockets发送一些数据。
  4. 当服务器通过套接字
  5. 收到回复时,请求已完成

    以下是我的设置:

    io.on('connection', function(client) {
        client.setMaxListeners(0);
    
        client.on('answer', (data) => {
            console.log(data);
            console.log(request_queue.workersList());
    
            returnResponse(data, request_queue.workersList()[0].data, request_queue.workersList()[0].callback);
        })
    });
    
    var request_queue = asyn.queue(requestHandler, 1);
    
    app.post('/', function(request, response) {
    
        request_queue.push({req: request, res: response}, () => {
            console.log("pushed new request");
        });
    
        console.log(request_queue.length());
    
    });
    
    function requestHandler(req_res, finish) {
    
        // Do something with the data received in the request
    
        io.sockets.emit('update_img', JSON.stringify(data_to_send));
    
    }
    
    function returnResponse(data, res_req, finish) {
        data = JSON.parse(data);
        var res = res_req.res;
    
        var error = data.error;
    
        if (error) {
            console.log("I WAS HERE");
            error = {};
            error['error'] = 'There has been an error!'
            res.json(error);
            finish("There was an error");
        }
    
        // send back actual response
    
        res.json(data);
        console.log("Right before finish");
        finish();
    }
    

    不幸的是,这会产生以下错误:

    GET / 304 3.845 ms - -
    1
    [Function]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    DATA_RECEIVED
    [ { data: { req: [Object], res: [Object] },
        callback: [Function],
        next: null,
        prev: null } ]
    Right before finish
    pushed new request
    POST / 200 7901.287 ms - 267
    16
    17
    18
    19
    20
    21
    22
    23
    24
    DATA_RECEIVED
    [ { data: { req: [Object], res: [Object] },
        callback: [Function],
        next: null,
        prev: null } ]
    _http_outgoing.js:489
        throw new Error('Can\'t set headers after they are sent.');
        ^
    

    所以在我看来,worker函数还没有正确完成,否则响应对象会是另一个对吧?我不确定我是否已使用request_queue.workersList()[0].callback正确传递了worker的回调函数。

    任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

必须有一种更简单的方法来做到这一点。让我们添加一个全局回调映射,我们可以存储每个进程的回调。为此,我们需要通过唯一ID识别套接字/ POST:

 const callbacks = new Map();

 io.on('connection', function(client) {
  client.setMaxListeners(0);

  client.on('answer', (data) => {
    console.log(data);     
    const cb = callbacks.get(data.id /*TODO*/);
    if(!cb) return client.emit("error","process with that id not found");
    cb(data);
    callbacks.delete(data.id);
  })
});

所以现在我们可以向套接字添加一个回调,它只会调用一次。可以这样使用:

 app.post("/:id", function(req, res){
   callbacks.set( req.params.id, data => {
     res.json(data);
   });
});

如果您想在一段时间后终止POST请求(以防止DOS攻击),您可能会使用简单的超时:

app.post("/:id", function(req, res){
   callbacks.set( req.params.id, data => {
     res.json(data);
   });
   //recycle after inactive time:
   setTimeout( id => {
     if( !callbacks.has(id) ) return; //all fine, user answered already
     callbacks.delete(id);
     res.json({ error: "no answer from socket"});
  }, 10000, req.params.id);
});