I'm using express,socketio and socketio-client in my application. (I not very comfortable with nodejs stack...)
to summarize my application flow : Client => node/express API + Socketoi server <=> nodejs (Socketio-client)
- browser send request to a nodejs/express (route /api)
- Do some request headers overwrites with middlewares
- In the route '/', server sends an emit to a nodejs (Socketio-client)
- after executing some logic, socketio-client emit an event with the logics result
- I need this result to be send in the response to the client
My code below:
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);
});
}
});
My problem : This works only the first time I send a Get http://localhost:3000/api frome the browser. __res.body is printed in the browser.
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
Next request will just wait for server to respond, which is, I suspect, not happening because the app.io.__socket.on('respp', function (data){...} is never catched by the server.
After sending more request (while the others are waiting), I noticed this warning in server logs:
(node) warning: possible EventEmitter memory leak detected. 11 respp listeners added. Use emitter.setMaxListeners() to increase limit.
Is there other ways to catch events in a route before sending response to clients?
You could remove the event listener when the socket closes to avoid the event listener leak:
I'm not sure if
app.io.__socket
should really beapp.io.sockets
or not, but I copied it as-is from your code, assuming you know what you're doing.Additionally, you may wish to add some sort of timeout so as not to keep the request waiting indefinitely.
I solved with
once
: