我做的socket.io实现是错误的。我正在尝试对mysql数据实现长轮询。
对于此演示,我将为连接到我创建的长轮询服务器的每个用户提取用户数据。每个用户将其唯一的user_id传递给服务器以获取与他/她相关的数据。 (在真实应用中,我想获取用户通知)
用户连接到服务器,服务器也会从数据库进行长轮询。但问题是,即使我从客户端传递了唯一的ID,同样的数据也被推回到客户端。
用户1传递了id 5,用户2传递了id 3.这两个用户获得的数据与响应相同(用户1的数据)
以下是客户端代码:
var user_id = 5; //hardcoded for now, but in real its fetched from a form
var params = {
userId: user_id,
};
// create a new websocket
var socket = io.connect('http://localhost:8000', { query: params });
// on message received we print all the data inside the #container div
socket.on('notification', function (data) {
console.log(data);
});
这是服务器端代码:
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
mysql = require('mysql'),
connectionsArray = [],
connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'dumydb',
port: 3306
}),
POLLING_INTERVAL = 5000,
pollingTimer;
// If there is an error connecting to the database
connection.connect(function (err) {
// connected! (unless `err` is set)
if (err) {
console.log(err);
}
});
// creating the server ( localhost:8000 )
app.listen(8000);
// on server started we can load our client.html page
function handler(req, res) {
fs.readFile(__dirname + '/client.html', function (err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading client.html');
}
res.writeHead(200);
res.end(data);
});
}
// creating a new websocket to keep the content updated without any AJAX request
io.sockets.on('connection', function (socket) {
var userId = socket.handshake.query.userId;
// starting the loop only if at least there is one user connected
if (!connectionsArray.length) {
pollingLoop(userId);
}
socket.on('disconnect', function () {
var socketIndex = connectionsArray.indexOf(socket);
console.log('socketID = %s got disconnected', socketIndex);
if (~socketIndex) {
connectionsArray.splice(socketIndex, 1);
}
});
console.log('A new socket is connected!');
connectionsArray.push(socket);
});
var pollingLoop = function (userId) {
var params = [userId];
// Doing the database query
var tempQuery = `SELECT full_name FROM users WHERE id=?`;
var query = connection.query(tempQuery, params),
users = []; // this array will contain the result of our db query
// setting the query listeners
query
.on('error', function (err) {
// Handle error, and 'end' event will be emitted after this as well
updateSockets(err);
})
.on('result', function (user) {
// it fills our array looping on each user row inside the db
users.push(user);
})
.on('end', function () {
// loop on itself only if there are sockets still connected
if (connectionsArray.length) {
pollingTimer = setTimeout(function () { pollingLoop(userId) }, POLLING_INTERVAL);
updateSockets({
users: users
});
} else {
console.log('The server timer was stopped because there are no more socket connections on the app')
}
});
};
var updateSockets = function (data) {
// adding the time of the last update
data.time = new Date();
// sending new data to all the sockets connected
connectionsArray.forEach(function (tmpSocket) {
tmpSocket.volatile.emit('notification', data);
});
};
console.log('Please use your browser to navigate to http://localhost:8000');
这是我正在关注的教程:Link
任何人都可以帮我弄清楚为什么同一数据被推送给所有用户?谢谢!
更新1
我尝试了Theo和Abdul Rab Memon提供的解决方案 更改了我的updateSockets()但现在数据只被推送到连接的第一个客户端。我做了一个console.log() 看看这个:
更新2 :package.json
{
"name": "nodejs-MySQL-push-notifications-demo",
"version": "1.0.0",
"description": "nodejs-MySQL-push-notifications-demo",
"main": "server.js",
"dependencies": {
"express": "^4.16.2",
"mysql": "~2.5.4",
"socket.io": "~1.3.2"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "git://github.com/GianlucaGuarini/nodejs-MySQL-push-notifications-demo.git"
},
"author": "Gianluca Guarini",
"license": "BSD-2-Clause",
"bugs": {
"url": "https://github.com/GianlucaGuarini/nodejs-MySQL-push-notifications-demo/issues"
},
"homepage": "https://github.com/GianlucaGuarini/nodejs-MySQL-push-notifications-demo"
}
答案 0 :(得分:6)
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
mysql = require('mysql'),
connectionsArray = [],
connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'dumydb',
port: 3306
}),
POLLING_INTERVAL = 5000,
pollingTimer;
// If there is an error connecting to the database
connection.connect(function (err) {
// connected! (unless `err` is set)
if (err) {
console.log(err);
}
});
// creating the server ( localhost:8000 )
app.listen(8000);
// on server started we can load our client.html page
function handler(req, res) {
fs.readFile(__dirname + '/client.html', function (err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading client.html');
}
res.writeHead(200);
res.end(data);
});
}
// creating a new websocket to keep the content updated without any AJAX request
io.sockets.on('connection', function (socket) {
var userId = socket.handshake.query.userId;
connectionsArray.push(socket);
// starting the loop only if at least there is one user connected
if (connectionsArray.length) {
var socketIndex = connectionsArray.indexOf(socket);
pollingLoop(userId, socketIndex);
}
socket.on('disconnect', function () {
var socketIndex = connectionsArray.indexOf(socket);
console.log('socketID = %s got disconnected', socketIndex);
if (~socketIndex) {
connectionsArray.splice(socketIndex, 1);
}
});
console.log('A new socket is connected!');
});
var pollingLoop = function (userId, socketIndex) {
var params = [userId];
// Doing the database query
var tempQuery = `SELECT full_name FROM users WHERE id=?`;
var query = connection.query(tempQuery, params),
users = []; // this array will contain the result of our db query
// setting the query listeners
query
.on('error', function (err) {
// Handle error, and 'end' event will be emitted after this as well
updateSockets(err, socketIndex);
})
.on('result', function (user) {
// it fills our array looping on each user row inside the db
users.push(user);
})
.on('end', function () {
// loop on itself only if there are sockets still connected
if (connectionsArray.length) {
pollingTimer = setTimeout(function () { pollingLoop(userId) }, POLLING_INTERVAL);
updateSockets({
users: users
}, socketIndex);
} else {
console.log('The server timer was stopped because there are no more socket connections on the app')
}
});
};
var updateSockets = function (data, socketIndex) {
// adding the time of the last update
data.time = new Date();
// sending new data to all the sockets connected
connectionsArray[socketIndex].volatile.emit('notification', data);
};
console.log('Please use your browser to navigate to http://localhost:8000');
在updateSockets方法中,您将重复遍历connectionsArray并发出通知'如果事件包含在connectionsArray中存在的每个套接字上的数据,则需要将套接字从socket.on(' connection',callback(socket))传递给pollingLoop方法,并从pollingLoop传递到updatSocket方法。
答案 1 :(得分:2)
由于您提到要提取与用户相关的数据,因此您需要向
var userList = {};
io.on('connection', (socket) => {
usersList[socket.handshake.query.userId].socket_id = socket.id;
});
成功投票后,您可以发送给这样的特定用户 请注意您可以从pollingLoop传递的附加参数userId
var updateSockets = function (data, userId) {
// adding the time of the last update
data.time = new Date();
// sending new data to the specific socket connected
io.sockets.to(userList[userId].socket_id).emit('notification', data);
};
您可以尝试使用名称空间或房间发送给组。所以而不是
connectionsArray.forEach(function (tmpSocket) {
tmpSocket.volatile.emit('notification', data);
});
您可以使用命名空间
客户代码
var socket = io.connect('http://localhost:8000/your_name_space', { query: params });
服务器代码
io.of('/your_name_space').emit('notification', data_to_be_sent);
或群组 - 有关会议室https://socket.io/docs/rooms-and-namespaces/的更多信息,请参阅此链接