在快速路线内等待socketio事件

我在我的应用程序中使用express,socketio和socketio-client。 (我不是很喜欢nodejs堆栈…)

总结我的应用程序stream程:Client => node / express API + Socketoi server <=> nodejs(Socketio-client)

  1. 浏览器发送请求到一个nodejs / express(route / api)
  2. 做一些请求标题覆盖中间件
  3. 在路由“/”中,服务器发送一个发送给nodejs(Socketio-client)
  4. 在执行一些逻辑之后,socketio-client用逻辑结果发出一个事件
  5. 我需要这个结果发送到客户端的响应

我的代码如下:

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',函数(数据){…}。

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

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

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

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

 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 ,但是我假设你知道你在做什么,而是从你的代码中复制它。

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

once解决once

 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 }); });