套接字IO广播到房间不能正常工作

时间:2019-01-05 02:41:34

标签: javascript node.js socket.io pug mean-stack

如果这是一个模糊的问题,请告诉我,以便我指定。我真的很想解决这个问题。

我已经阅读了几本有关如何正确向客户室广播消息的备忘单。我的参考是: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')
})

3 个答案:

答案 0 :(得分:0)

尝试

io.in(rooms).emit('chat', data);

答案 1 :(得分:0)

global.rooms = 'room1';下缺少此

var rooms = global.rooms

更长的答案:至少我能看到,您已经在全局对象上添加了“ rooms”作为属性(idk定义了“ global”本身,但如果没有抛出错误,我假设您在上面定义)。虽然它是一个属性,但是在调用它时未定义您用作命名空间的变量“ rooms”,因此它不知道在哪里发出消息。

更多答案:另外,如果您打算向global.rooms添加其他房间,我想您可能希望使用哈希表存储它们,以便可以以global.rooms[room]的身份轻松访问它们,以及轻松地将新房间添加到列表中,例如global.rooms[room.name] = room

答案 2 :(得分:0)

问题是您未指定在何处呈现消息。据我了解,创建房间没有问题,因此,在此之后,我将逐步说明如何处理。

根据您的代码,这是服务器和客户端之间用于发送消息的通信

//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已重命名为哈巴狗,所以我在这里使用哈巴狗。因此,我将在脚本标签中将{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代码看起来很长而且很复杂,但是如果您知道逻辑并逐步进行,那么将很容易实现它。