在快速路线内等待 socketio 事件
Wait for socketio event inside express route
我在我的应用程序中使用了 express、socketio 和 socketio-client。
(我对 nodejs 堆栈不是很满意...)
总结一下我的申请流程:
客户端 => node/express API + Sockettoi 服务器 <=> nodejs (Socketio-client)
- 浏览器向nodejs/express发送请求(路由/api)
- 做一些请求headers 用中间件覆盖
- 在路由 '/' 中,服务器发送一个 emit 到 nodejs (Socketio-client)
- 执行一些逻辑后,socketio-client 发出带有逻辑结果的事件
- 我需要将此结果发送给客户端的响应
我的代码如下:
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.
是否有其他方法可以在向客户端发送响应之前捕获路由中的事件?
您可以在套接字关闭时删除事件监听器以避免事件监听器泄漏:
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
解决了:
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 });
});
我在我的应用程序中使用了 express、socketio 和 socketio-client。 (我对 nodejs 堆栈不是很满意...)
总结一下我的申请流程: 客户端 => node/express API + Sockettoi 服务器 <=> nodejs (Socketio-client)
- 浏览器向nodejs/express发送请求(路由/api)
- 做一些请求headers 用中间件覆盖
- 在路由 '/' 中,服务器发送一个 emit 到 nodejs (Socketio-client)
- 执行一些逻辑后,socketio-client 发出带有逻辑结果的事件
- 我需要将此结果发送给客户端的响应
我的代码如下:
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.
是否有其他方法可以在向客户端发送响应之前捕获路由中的事件?
您可以在套接字关闭时删除事件监听器以避免事件监听器泄漏:
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
解决了:
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 });
});