nodejs-socket.io服务器为所有用户推送相同的数据

我做的socket.io实现是错误的。 我想实现一个MySQL数据的长轮询。

对于这个演示,我为每个连接到我创build的长轮询服务器的用户提取用户数据。 每个用户都会将其唯一的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'); 

这是我正在遵循的教程: 链接

任何人都可以帮我找出为什么同样的数据被推送给所有用户? 谢谢!

更新1

我尝试了由Theo和Abdul Rab Memon提供的解决scheme更改了我的updateSockets(),但是现在数据只被推送到连接的第一个客户端。 我做了一个console.log()看看这个:

在这里输入图像描述

更新2package.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" } 

 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并发出“notification”事件,其中包含connectionsArray中存在的每个套接字上的数据,您需要将套接字从socket.on('connection',callback(套接字))传递给pollingLoop方法,从pollingLoop到updatSocket方法。

既然你提到你想获取有关用户的数据 ,你需要发送到特定的客户端套接字 。 为此,每次连接时都需要保存客户端的socket.id。 你可以这样做:

 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/