每次用户添加新数据时,节点都会多次发回数据
Node sends data back multiple times everytime a user adds new data
首先,我想为这个措辞糟糕的标题道歉;在过去的 20 分钟里,我一直在努力想出一个办法,但我不知道用一种简洁的方式来描述我遇到的问题。如果有人有更好的建议,请告诉我或编辑标题(如果可以)。
背景: 为了学习NodeJS,我正在创建一个聊天服务器。当用户点击createRoomBtn
时,创建一个包含用户刚刚创建的房间名称的事件,并发送到app.js
中的socket.js
模块,app.js然后追加将房间添加到房间数组(这些房间在浏览器中显示为列表),并为包括活动用户在内的所有用户创建广播事件。
问题:假设有一个空列表,用户添加了一个新房间,标题为 "NodeJS",这将在屏幕上显示房间,以及所有内容很好,花花公子。现在,如果我要添加另一个房间 Socket.io,浏览器将呈现以下结果:Socket.io, NodeJS, NodeJS
。如果我要添加 "Javascript",结果将是 Javascript, Socket.io, NodeJS, Socket.io, Node.JS
。基本上,浏览器会一遍又一遍地渲染列表,每次列表都会缩小一个。我完全不知道为什么会这样。奇怪的是,如果我按刷新,浏览器会正确呈现列表 Javascript, Socket.io, NodeJS
。怎么回事?
socket.js:
module.exports = function(io, rooms) {
var chatrooms = io.of('/roomlist').on('connection', function(socket) { //io.of creates a namespace
console.log('Connection established on the server');
socket.emit('roomupdate', JSON.stringify(rooms));
socket.on('newroom', function(data) {
console.log(data);
rooms.push(data);
socket.broadcast.emit('roomupdate', JSON.stringify(rooms));
socket.emit('roomupdate', JSON.stringify(rooms));
})
})
var messages = io.of('/messages').on('connection', function(socket) {
console.log('Connected to the chatroom!');
socket.on('joinroom', function(data) {
socket.username = data.user;
socket.userpic = data.userPic;
socket.join(data.room);
})
socket.on('newMessage', function(data) {
socket.broadcast.to(data.room_number).emit('messagefeed', JSON.stringify(data));
})
})
}
chatrooms.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" href="../css/chatrooms.css">
<script src="//code.jquery.com/jquery-1.11.0.min.js"> </script>
<script src="/socket.io/socket.io.js"> </script>
<script>
$(function() {
var host = '{{config.host}}';
var socket = io.connect(host + '/roomlist');
socket.on('connect', function() {
console.log('connection established');
})
socket.on('roomupdate', function(data) {
$('.roomlist').html('');
var procData = JSON.parse(data);
for (var i = 0; i < procData.length; i++) {
var str = '<a href="room/' + procData[i].room_number + '"><li>'
+ procData[i].room_name + '<li></a>';
$('.roomlist').prepend(str);
console.log(str);
}
})
$(document).on('click', '#createRoomBtn', function() {
var room_name = $('#newRoomText').val();
console.log(room_name);
if (room_name != '') {
var room_number = parseInt(Math.random() * 10000);
socket.emit('newroom', {room_name: room_name, room_number: room_number});
$('#newRoomText').val('');
}
})
})
</script>
</head>
<body>
<div class="cr-userbox">
<img src="{{user.profilePic}}" class="userPic">
<h3 class="username">{{user.fullName}}| <a href="/logout">Logout</a></h3>
</div>
<div class="cr-container">
<h1> ChatRooms</h1>
<div class="cr-newroom">
<input type="text" id="newRoomText" autocomplete="off">
<input type="submit" id="createRoomBtn" value=" Create Room">
</div>
<div class="cr-roomlist">
<ul class="roomlist">
</ul>
</div>
</div>
</body>
</html>
如果需要更多 information/modules,请告诉我,我很乐意提供。
Update1:正如 alex-rokabilis 正确建议的那样,我已将 $('.roomlist').html() = ''
更改为 $('.roomlist').html('')
,但是,问题仍然存在。
我认为问题在于您如何在 html 部分渲染您的房间,而不是 socket.io 如何发送数据。
您使用 $('.roomlist').html='';
但这没有做任何事情! .html
是 jquery 中的一个函数,所以正确的做法是 $('.roomlist').html('');
.
所以基本上你没有删除以前的房间,而是你只添加了更多重复项。另外我注意到这不是你问题的一部分,在你使用的 nodejs 代码中:socket.broadcast.emit('roomupdate', JSON.stringify(rooms));
socket.emit('roomupdate', JSON.stringify(rooms));
如果你想向所有连接的客户端广播一些东西,有一个函数可以做到,而且不需要对你的数据进行字符串化,socketio 会在内部为你做这件事!所以你可以使用这样的东西:
io.emit('roomupdate',rooms);
我不确定这是否是您的问题的原因,但您得到的是嵌套列表元素,因为您的 socket.on 中有两个起始 <li>
标记('roomupdate') 函数
首先,我想为这个措辞糟糕的标题道歉;在过去的 20 分钟里,我一直在努力想出一个办法,但我不知道用一种简洁的方式来描述我遇到的问题。如果有人有更好的建议,请告诉我或编辑标题(如果可以)。
背景: 为了学习NodeJS,我正在创建一个聊天服务器。当用户点击createRoomBtn
时,创建一个包含用户刚刚创建的房间名称的事件,并发送到app.js
中的socket.js
模块,app.js然后追加将房间添加到房间数组(这些房间在浏览器中显示为列表),并为包括活动用户在内的所有用户创建广播事件。
问题:假设有一个空列表,用户添加了一个新房间,标题为 "NodeJS",这将在屏幕上显示房间,以及所有内容很好,花花公子。现在,如果我要添加另一个房间 Socket.io,浏览器将呈现以下结果:Socket.io, NodeJS, NodeJS
。如果我要添加 "Javascript",结果将是 Javascript, Socket.io, NodeJS, Socket.io, Node.JS
。基本上,浏览器会一遍又一遍地渲染列表,每次列表都会缩小一个。我完全不知道为什么会这样。奇怪的是,如果我按刷新,浏览器会正确呈现列表 Javascript, Socket.io, NodeJS
。怎么回事?
socket.js:
module.exports = function(io, rooms) {
var chatrooms = io.of('/roomlist').on('connection', function(socket) { //io.of creates a namespace
console.log('Connection established on the server');
socket.emit('roomupdate', JSON.stringify(rooms));
socket.on('newroom', function(data) {
console.log(data);
rooms.push(data);
socket.broadcast.emit('roomupdate', JSON.stringify(rooms));
socket.emit('roomupdate', JSON.stringify(rooms));
})
})
var messages = io.of('/messages').on('connection', function(socket) {
console.log('Connected to the chatroom!');
socket.on('joinroom', function(data) {
socket.username = data.user;
socket.userpic = data.userPic;
socket.join(data.room);
})
socket.on('newMessage', function(data) {
socket.broadcast.to(data.room_number).emit('messagefeed', JSON.stringify(data));
})
})
}
chatrooms.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{title}}</title>
<link rel="stylesheet" href="../css/chatrooms.css">
<script src="//code.jquery.com/jquery-1.11.0.min.js"> </script>
<script src="/socket.io/socket.io.js"> </script>
<script>
$(function() {
var host = '{{config.host}}';
var socket = io.connect(host + '/roomlist');
socket.on('connect', function() {
console.log('connection established');
})
socket.on('roomupdate', function(data) {
$('.roomlist').html('');
var procData = JSON.parse(data);
for (var i = 0; i < procData.length; i++) {
var str = '<a href="room/' + procData[i].room_number + '"><li>'
+ procData[i].room_name + '<li></a>';
$('.roomlist').prepend(str);
console.log(str);
}
})
$(document).on('click', '#createRoomBtn', function() {
var room_name = $('#newRoomText').val();
console.log(room_name);
if (room_name != '') {
var room_number = parseInt(Math.random() * 10000);
socket.emit('newroom', {room_name: room_name, room_number: room_number});
$('#newRoomText').val('');
}
})
})
</script>
</head>
<body>
<div class="cr-userbox">
<img src="{{user.profilePic}}" class="userPic">
<h3 class="username">{{user.fullName}}| <a href="/logout">Logout</a></h3>
</div>
<div class="cr-container">
<h1> ChatRooms</h1>
<div class="cr-newroom">
<input type="text" id="newRoomText" autocomplete="off">
<input type="submit" id="createRoomBtn" value=" Create Room">
</div>
<div class="cr-roomlist">
<ul class="roomlist">
</ul>
</div>
</div>
</body>
</html>
如果需要更多 information/modules,请告诉我,我很乐意提供。
Update1:正如 alex-rokabilis 正确建议的那样,我已将 $('.roomlist').html() = ''
更改为 $('.roomlist').html('')
,但是,问题仍然存在。
我认为问题在于您如何在 html 部分渲染您的房间,而不是 socket.io 如何发送数据。
您使用 $('.roomlist').html='';
但这没有做任何事情! .html
是 jquery 中的一个函数,所以正确的做法是 $('.roomlist').html('');
.
所以基本上你没有删除以前的房间,而是你只添加了更多重复项。另外我注意到这不是你问题的一部分,在你使用的 nodejs 代码中:socket.broadcast.emit('roomupdate', JSON.stringify(rooms));
socket.emit('roomupdate', JSON.stringify(rooms));
如果你想向所有连接的客户端广播一些东西,有一个函数可以做到,而且不需要对你的数据进行字符串化,socketio 会在内部为你做这件事!所以你可以使用这样的东西:
io.emit('roomupdate',rooms);
我不确定这是否是您的问题的原因,但您得到的是嵌套列表元素,因为您的 socket.on 中有两个起始 <li>
标记('roomupdate') 函数