在快速路线内等待socketio事件

时间:2015-08-13 15:34:53

标签: javascript node.js express socket.io

我在我的应用程序中使用express,socketio和socketio-client。 (我对nodejs堆栈不太满意......)

总结我的申请流程: 客户=) node / express API + Socketoi server< => nodejs(Socketio-client)

  1. 浏览器向nodejs / express(route / api)发送请求
  2. 使用中间件覆盖某些请求标头
  3. 在路由'/'中,服务器向nodesjs发送一个emit(Socketio-client)
  4. 执行一些逻辑后,socketio-client发出一个带有逻辑结果的事件
  5. 我需要将此结果发送到对客户的回复
  6. 我的代码如下:

    router.get('/*', function (req, res) {
      //emit data for socketio-client to apply some logic
      app.io.sockets.emit('req', {
        reqheader : req.headers,
        requrl : req.protocol + "://" + req.headers.host + req.url,
        reqmethod : req.method
      });
      console.log("after emit");
      //I use callback to make response wait for socketio server to catch event from client
      waitforevent(req, res, function (__res) {
        console.log("callback" );
        res.end(__res.body);
        res.sendStatus(__res.statusCode);
        //res.end();
      });
      function waitforevent(req, res, callback) {
        console.log("waiting for event" );
        app.io.__socket.on('respp', function (data) {
            //console.log("no response yet \n" + JSON.parse(data) );
            __res = JSON.parse(data);
            console.log("event catched...");
            callback(__res);
        });
      }
    });
    

    我的问题: 这仅在我第一次向浏览器发送Get http://localhost:3000/api时才有效。 __ res.body 会在浏览器中打印出来。

    req 1
    after emit
    waiting for event
    event catched...
    callback
    Error: Can't set headers after they are sent.   
    **GET /api 200 73.841 ms - -**
    
    req 2
    after emit
    waiting for event
    

    下一个请求将等待服务器响应,我怀疑,这不会发生,因为app.io .__ socket.on('respp',function(data){...}从未被服务器捕获

    发送更多请求后(其他人正在等待),我在服务器日志中发现了这个警告:

    (node) warning: possible EventEmitter memory leak detected. 11 respp listeners added. Use emitter.setMaxListeners() to increase limit.
    

    在向客户发送回复之前,还有其他方法可以捕获路线中的事件吗?

2 个答案:

答案 0 :(得分:1)

您可以在套接字关闭时删除事件侦听器以避免事件侦听器泄漏:

router.get('/*', function (req, res) {
  app.io.sockets.emit('req', {
    reqheader : req.headers,
    requrl : req.protocol + "://" + req.headers.host + req.url,
    reqmethod : req.method
  });

  req.socket.on('close', function() {
    app.io.__socket.removeListener('respp', resppHandler);
  });
  app.io.__socket.on('respp', resppHandler);

  function resppHandler(data) {
    data = JSON.parse(data);
    res.statusCode = data.statusCode;
    res.end(data.body);
  }
});

我不确定app.io.__socket是否真的应该app.io.sockets,但我会将其原样从您的代码中复制出来,假设您知道自己在做什么。< / p>

此外,您可能希望添加某种超时,以免让请求无限期等待。

答案 1 :(得分:0)

我用var app = require('express')(); var server = require('http').Server(app); var io = require('socket.io')(server); var socket; io.on('connection', function (sock) { console.log('Connected'); socket = sock; }); server.listen(3000); app.get('/*', function (req, res) { socket.once('event', function (data) { if (data.error) { console.log('is an error'); res.status(400).json(data); } else { console.log('is ok'); res.status(200).json(data); } }); io.emit('ask-for-event', { data: data }); }); 解决了:

pod 'Fabric'
pod 'Crashlytics', '3.1.1'