亲爱的朋友们,我在尝试跟踪聊天中的登录用户时遇到了一个小问题。聊天基于两个在命名空间的帮助下工作的单独通道:
-
chatInfra
- 处理登录用户并发送欢迎消息。 -
chatCom
- 处理用户之间的消息传递。
我搜索了很多,但我只找到了理论上的解释,即最好的解决方案是将用户存储到数组中。因此,我试图通过将登录用户存储在数组中然后遍历它们来跟踪登录用户,但结果仍然不好。
问题是进入聊天后,屏幕上只显示第一个登录用户的姓名,而第二个用户的姓名不可见。
这是我的服务器端代码,我正在尝试将用户存储到clients
数组中:
var clients = [];
var chatInfra = io.of("/chat_infra").on("connection", function(socket){
socket.on("set_name", function (data) {
clients.push(data.name);
socket.emit('name_set', data);
socket.send(JSON.stringify({
type:'serverMessage',
message:'Welcome!'
}));
socket.broadcast.emit('user_entered', data);
});
});
var chatCom = io.of("/chat_com").on("connection", function (socket) {
socket.on('message', function (message) {
message = JSON.parse(message);
for(var key in clients){
if(message.type == "userMessage"){
message.username = clients[key];
console.log('message : ', message);
socket.broadcast.send(JSON.stringify(message));
message.type = "myMessage";
socket.send(JSON.stringify(message));
}
}
});
});
以下是它在浏览器中的外观:http://screencast.com/t/lshnfcGZ8E8
以下是完整的代码: https://gist.github.com/johannesMatevosyan/0b9f7e588338dbb6b7f5
我认为您通过使用不同的命名空间造成了不必要的矫枉过正。下面是实现相同功能的更清晰的工作示例:
服务器.js
var app = require("express")();
var server = require("http").Server(app);
var io = require("socket.io")(server);
var chat = io.of("/chat").on("connection", function(socket){
socket.on("set_name", function (data) {
socket.username = data.name;
socket.emit("name_set", data);
socket.emit("message", {
type :"serverMessage",
message :"Welcome!"
});
chat.emit("message", {
type :"serverMessage",
message : data.name + " has joined the room.!"
});
});
socket.on("message", function (message) {
message.username = socket.username;
chat.emit("message", message);
});
});
app.get("/", function (req, res) {
res.sendfile(__dirname + "/index.html");
});
server.listen(3000);
客户端.js
var socket = io.connect('http://localhost:3000/chat');
socket.on('name_set', function (data) {
$('#nameform').hide();
$('#messages').append('<div class="systemMessage">Hello ' + data.name + '</div>');
});
socket.on('message', function (message) {
var userNameHtml = message.username ? '<span class="name">' + message.username + ':</span>' : '';
$('#messages').append('<div class="' + message.type + '">' + userNameHtml + message.message + '</div>');
});
$(function () {
$('#setname').click(function () {
socket.emit("set_name", { name: $('#nickname').val() });
});
$('#send').click(function () {
socket.emit("message", {
message : $('#message').val(),
type : 'userMessage'
});
$('#message').val('');
});
});
我认为您不需要单独的事件处理程序来user_entered
,因为您将其视为常规消息,并且不对事件执行任何其他操作。还有几件事:
- 您不需要先连接到服务器,然后再连接到命名空间地址,连接到后者就可以了。
- 不要在回调中设置事件侦听器,这将导致多次设置它们。