广播到房间的套接字 IO 无法正常工作
Socket IO broadcasting to room is not functioning correctly
如果这是一个模糊的问题,请让我知道,以便我指定。真想绕过这个树桩
我已经阅读了一些关于如何正确地将消息广播到客户房间的备忘单。我的参考是:https://github.com/socketio/socket.io/blob/master/docs/emit.md.
描述我的问题:
聊天页面正确显示了发送按钮,但是一旦我点击发送,就什么也没有发送。
有趣的是,每当我不使用房间时,只要使用默认命名空间,我就可以收到消息。
知道发生了什么事吗?谢谢!!
server.js
io.on('connection', function(socket) {
global.rooms = 'room1';
socket.on('subscribe', function(room) {
socket.join(rooms);
console.log(socket.id + 'joining room', rooms)
})
socket.on('chat', function(data) {
io.to(rooms).emit('chat', data);
})
})
chat.jade
extends layout
block content
h2.page-header Chat Page
div(id='the-chat')
div(id='chat-window')
div(id='output')
input(id='handle', type='text', value = user.name, style= 'width: 0px; visibility: hidden;')
input(id='message', type='text', placeholder='message')
button(id='send' value='Send') Send
//imports the socket.io functionality on the client side for the chat.jade application
script(src="/socket.io/socket.io.js")
script.
//variable created that mirrors connection made in the backend
//matches the connection made in the server side
var socket = io.connect('http://localhost:3000')
//Query dom
var message = document.getElementById('message')
var handle = document.getElementById('handle')
var btn = document.getElementById('send')
var output = document.getElementById('output')
//emit events
btn.addEventListener('click', function() {
socket.emit('chat', {
message: message.value,
handle: handle.value
})
})
socket.on('chat', function(data) {
output.innerHTML += '<p><strong>' + data.handle + ': </strong>' + data.message + '</p>';
document.getElementById('message').value = "";
})
Home.jade
extends layout
block content
h2.page-header(style = "text-align: center;").
Home Page
if (user.isTutor)
b(style = "text-align: center;")
form(method='post', action = '/home/available')
input.btn.btn-primary(type = 'submit',name='isAvailable', value = 'Available', id = 'button4')
form(method='post', action = '/home/unavailable')
input.btn.btn-primary(type = 'submit',name='isUnavailable', value = 'Unavailable', id = 'button5')
script(src="/socket.io/socket.io.js")
script.
var btn = document.getElementById('button4')
//var space = '#{user.room}'
var socket = io.connect()
btn.addEventListener('click', function() {
socket.emit('subscribe', 'room1')
})
div(id = 'magic')
form(method='get')
if (user.hasApplied)
input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/findatutor';" name='find', value = 'Find a Tutor', class = 'middle', id = 'button7')
else if (user.hasApplied == false)
input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/findatutor';" name='find', value = 'Find a Tutor', id = 'button1')
input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/apply';" name='become', value = 'Become a Tutor', id = 'button2')
Home.js
router.post('/available', ensureAuthenticated, (req,res,next) => {
var io = res.locals['socketio']
db.collection('DefaultUser').update({_id: req.user._id}, {$set: {isAvailable: true}});
res.redirect('../chat')
})
尝试
io.in(rooms).emit('chat', data);
global.rooms = 'room1';
下缺少这个
var rooms = global.rooms
更长的答案:至少我可以看到,您已经在全局对象上添加了 "rooms" 作为 属性(idk,其中定义了 'global' 本身,但是如果它是没有抛出错误,我假设你在上面定义了它)。虽然它是 属性,但您用作命名空间的变量 'rooms' 在您调用它时并未定义,因此它不知道在哪里发出消息。
更多答案:此外,如果您打算向 global.rooms 添加额外的房间,我认为您可能希望使用散列列表来存储它们,以便您可以轻松地访问它们 global.rooms[room]
,以及轻松将新房间添加到列表中,即 global.rooms[room.name] = room
问题是您没有指定在何处呈现消息。据我了解,您创建房间没有问题,所以我将逐步说明之后如何处理。
根据您的代码,这是服务器和客户端之间用于发送消息的通信
//server.js
socket.on('chat', function(data) {
io.to(rooms).emit('chat', data);
})
//chat.jade
btn.addEventListener('click', function() {
socket.emit('chat', {
message: message.value,
handle: handle.value
})
})
第一个客户端正在向服务器发送消息(输入输入框),当服务器收到消息时,它必须向所有其他客户端发送相同的消息。一旦客户收到此消息,客户就必须弄清楚如何显示它。但是当服务器发送接收到的消息时,你必须发起一个新的事件。让我们称之为显示。所以你的代码应该是这样的:
//server.js
//i always use arrow functions, but I will follow along your code
socket.on('chat', function(data) {
io.to(rooms).emit('display', data);
})
现在您的客户端应该正在侦听此事件并且应该处理在何处显示它:
//chat.jade
socket.on('display', (data) => {
const displayedMessage = pug.render(messageTemplate, {
message: data.message,
})
$messages.insertAdjacentHTML('beforeend', displayedMessage)
})
由于 Jade 已重命名为 pug,因此我在这里使用 pug。所以我将在脚本标签中将 {message: data.message} 渲染到 html 然后将其放入 DOM ELEMENT $message.
我不确定你想在哪里呈现 handle:handle.value
我将只展示如何显示消息。同样,你也能搞定。
现在 messageTemplate
、$messages
和 insertAdjacentHTML() 是什么?
在您的 html
中创建一个 div 标签和一个脚本标签
//this is where you are gonna display the message
<div id="messages" class="chat__messages"></div>
<!-- template messages -->
<script id="message-template" type="text/html">
<div>
<p>{{message}}</p>
</div>
</script>
//chat.jade
const $messages = document.getElementById("messages");
const messageTemplate = document.getElementById("message-template").innerHTML;
insertAdjacentHTML() 方法将文本 HTML 插入指定位置。你可以在这里得到更多的解释和例子:
https://www.w3schools.com/jsref/met_node_insertadjacenthtml.asp
socket io代码看起来又长又复杂,但如果你知道逻辑并一步一步地进行,就会很容易实现它。
如果这是一个模糊的问题,请让我知道,以便我指定。真想绕过这个树桩
我已经阅读了一些关于如何正确地将消息广播到客户房间的备忘单。我的参考是:https://github.com/socketio/socket.io/blob/master/docs/emit.md.
描述我的问题: 聊天页面正确显示了发送按钮,但是一旦我点击发送,就什么也没有发送。
有趣的是,每当我不使用房间时,只要使用默认命名空间,我就可以收到消息。
知道发生了什么事吗?谢谢!!
server.js
io.on('connection', function(socket) {
global.rooms = 'room1';
socket.on('subscribe', function(room) {
socket.join(rooms);
console.log(socket.id + 'joining room', rooms)
})
socket.on('chat', function(data) {
io.to(rooms).emit('chat', data);
})
})
chat.jade
extends layout
block content
h2.page-header Chat Page
div(id='the-chat')
div(id='chat-window')
div(id='output')
input(id='handle', type='text', value = user.name, style= 'width: 0px; visibility: hidden;')
input(id='message', type='text', placeholder='message')
button(id='send' value='Send') Send
//imports the socket.io functionality on the client side for the chat.jade application
script(src="/socket.io/socket.io.js")
script.
//variable created that mirrors connection made in the backend
//matches the connection made in the server side
var socket = io.connect('http://localhost:3000')
//Query dom
var message = document.getElementById('message')
var handle = document.getElementById('handle')
var btn = document.getElementById('send')
var output = document.getElementById('output')
//emit events
btn.addEventListener('click', function() {
socket.emit('chat', {
message: message.value,
handle: handle.value
})
})
socket.on('chat', function(data) {
output.innerHTML += '<p><strong>' + data.handle + ': </strong>' + data.message + '</p>';
document.getElementById('message').value = "";
})
Home.jade
extends layout
block content
h2.page-header(style = "text-align: center;").
Home Page
if (user.isTutor)
b(style = "text-align: center;")
form(method='post', action = '/home/available')
input.btn.btn-primary(type = 'submit',name='isAvailable', value = 'Available', id = 'button4')
form(method='post', action = '/home/unavailable')
input.btn.btn-primary(type = 'submit',name='isUnavailable', value = 'Unavailable', id = 'button5')
script(src="/socket.io/socket.io.js")
script.
var btn = document.getElementById('button4')
//var space = '#{user.room}'
var socket = io.connect()
btn.addEventListener('click', function() {
socket.emit('subscribe', 'room1')
})
div(id = 'magic')
form(method='get')
if (user.hasApplied)
input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/findatutor';" name='find', value = 'Find a Tutor', class = 'middle', id = 'button7')
else if (user.hasApplied == false)
input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/findatutor';" name='find', value = 'Find a Tutor', id = 'button1')
input.btn.btn-primary(type = 'submit', onclick = "javascript: form.action = '/apply';" name='become', value = 'Become a Tutor', id = 'button2')
Home.js
router.post('/available', ensureAuthenticated, (req,res,next) => {
var io = res.locals['socketio']
db.collection('DefaultUser').update({_id: req.user._id}, {$set: {isAvailable: true}});
res.redirect('../chat')
})
尝试
io.in(rooms).emit('chat', data);
global.rooms = 'room1';
var rooms = global.rooms
更长的答案:至少我可以看到,您已经在全局对象上添加了 "rooms" 作为 属性(idk,其中定义了 'global' 本身,但是如果它是没有抛出错误,我假设你在上面定义了它)。虽然它是 属性,但您用作命名空间的变量 'rooms' 在您调用它时并未定义,因此它不知道在哪里发出消息。
更多答案:此外,如果您打算向 global.rooms 添加额外的房间,我认为您可能希望使用散列列表来存储它们,以便您可以轻松地访问它们 global.rooms[room]
,以及轻松将新房间添加到列表中,即 global.rooms[room.name] = room
问题是您没有指定在何处呈现消息。据我了解,您创建房间没有问题,所以我将逐步说明之后如何处理。
根据您的代码,这是服务器和客户端之间用于发送消息的通信
//server.js
socket.on('chat', function(data) {
io.to(rooms).emit('chat', data);
})
//chat.jade
btn.addEventListener('click', function() {
socket.emit('chat', {
message: message.value,
handle: handle.value
})
})
第一个客户端正在向服务器发送消息(输入输入框),当服务器收到消息时,它必须向所有其他客户端发送相同的消息。一旦客户收到此消息,客户就必须弄清楚如何显示它。但是当服务器发送接收到的消息时,你必须发起一个新的事件。让我们称之为显示。所以你的代码应该是这样的:
//server.js
//i always use arrow functions, but I will follow along your code
socket.on('chat', function(data) {
io.to(rooms).emit('display', data);
})
现在您的客户端应该正在侦听此事件并且应该处理在何处显示它:
//chat.jade
socket.on('display', (data) => {
const displayedMessage = pug.render(messageTemplate, {
message: data.message,
})
$messages.insertAdjacentHTML('beforeend', displayedMessage)
})
由于 Jade 已重命名为 pug,因此我在这里使用 pug。所以我将在脚本标签中将 {message: data.message} 渲染到 html 然后将其放入 DOM ELEMENT $message.
我不确定你想在哪里呈现 handle:handle.value
我将只展示如何显示消息。同样,你也能搞定。
现在 messageTemplate
、$messages
和 insertAdjacentHTML() 是什么?
在您的 html
中创建一个 div 标签和一个脚本标签//this is where you are gonna display the message
<div id="messages" class="chat__messages"></div>
<!-- template messages -->
<script id="message-template" type="text/html">
<div>
<p>{{message}}</p>
</div>
</script>
//chat.jade
const $messages = document.getElementById("messages");
const messageTemplate = document.getElementById("message-template").innerHTML;
insertAdjacentHTML() 方法将文本 HTML 插入指定位置。你可以在这里得到更多的解释和例子:
https://www.w3schools.com/jsref/met_node_insertadjacenthtml.asp
socket io代码看起来又长又复杂,但如果你知道逻辑并一步一步地进行,就会很容易实现它。