我想知道是否有人能帮我找出我做错了什么:
我的客户端网页启动与服务器的连接,并侦听一个长时间运行的进程,该进程的状态正在数据库中由另一个线程上的工作进程更新,并将更新发送回浏览器。我在app.post()方法中定义了一个socket.io连接。这是由下面的poll()函数处理的(向下滚动一点超过邀请检查代码)
然而,当一个新的web客户端连接时,它的消息会被添加到以前的客户端,就好像只有一个通道一样。为什么每个浏览器都没有一个单独的唯一频道?
//Create server
var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server);
io.set('log level', 1); // reduce logging
io.configure(function () {
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10);
});
app.post('/api/users', function (req, res) {
if (!req.body.auth.accessToken) {
req.body.auth.accessToken = req.body.auth.authResponse.accessToken;
} //fb return object is different depending on whether it is a first login or subsequent
logger.log('debug', '/api/users:POST', req.body);
io.sockets.on('connection', function (socket) {
socket = socket;
socket.emit('update', {
status: 200 //send initialization ping
});
//check if user has valid invite, if not try to invite
db.getTotalUserInvites(function (err_inv, res_total) {
db.getUserInvite(req.body.fid, function (err_check, res_check) {
logger.log('debug', 'Total invites issued=' + res_total);
//process report - all we need is accesToken, processReport will do the rest
mine_fb.processUser(req.body.auth.accessToken, socket, function (User,socket) { //pass channel properly
db.getReportStatus(User.fid,socket, function (result,socket) {
logger.log('debug', 'report status', result);
if (result) {
if (socket && (result.report_status == -1)) {
logger.log('debug', 'report already processed. retrieving uniq_id ' + result.uniq_id);
socket.emit('update', {
status: -1,
uniq_id: result.uniq_id
});
return true;
} else {
if (socket && (result.report_status >= 0)) {
logger.log('debug', 'we are in the middle of processing report ' + result.uniq_id);
//in this case we become a listener and not a speaker
function poll(socket) {
db.getReportStatus(User.fid, socket,function (r,socket) {
socket.emit('update', { //!!!! THIS EMITS TO ALL CONNECTED BROWSERS
status: r.report_status,
uniq_id: r.uniq_id
}); //...socket
if ((r.report_status >= 0) && (socket)) {
logger.log('debug', 'polling...');
_.delay(poll, 2000, socket);
}
}); //get rerpot
}; //end poll
socket.on('disconnect', function () {
socket=null;
});
poll(socket);
} // else we're in the middle
} //done checking status
} //end of seq
});
return res.send();
});
});
});
});
});
虽然还不清楚如何帮助您,但我可以告诉您的代码中发生了什么:
app.post('/api/users', function (req, res) {
// some code
io.sockets.on('connection', function (socket) {
// some code
});
});
每当用户将某个东西张贴到/api/users
时,就会将一个新的处理程序附加到io.sockets
(.on
就是这样做的)。但是这些处理程序永远不会被删除,所以每次建立新连接时,所有连接的处理程序都会激发。这就是你的广播来源。
您必须将app.post(...)
和io.sockets.on('connection',...)
分开(它们应该是独立的,都是在模块级别定义的,而不是嵌套的)。我相信这并不容易(例如,您可能需要对用户进行两次身份验证),但这是唯一合理的方法。
您不应该将io.sockets.on('connection', function (socket)
放在app.post
范围内。
只要把它放在外面再试一次,它可能会正常工作。
应在服务器启动时进行一次连接侦听,而不是每次客户端访问某个URL时都进行侦听。