【问题标题】:Socket.io - Cannot send messages to roomsSocket.io - 无法向房间发送消息
【发布时间】:2018-10-08 02:52:08
【问题描述】:
socket.on('join room', function (data) {
    var room = data.room;
    var msg = "<span style='color:darkgreen;'>" + data.user + " has joined chat.</span>";

    socket.join(room, function () {
        console.log(socket.id + " now in rooms ", socket.rooms);
    });

    io.in(room).emit('system message', msg);
});

如果我将io.in(room) 更改为socket.broadcast,系统消息就会通过。但无论出于何种原因,它都不会向特定房间发送消息,它什么也不做,也没有错误。有什么想法吗?

【问题讨论】:

  • 您是否尝试过在socket.join(room, function(){ // move it here ...} 回调中移动io.in(room).emit('system message', msg);
  • 只是按照您的建议进行操作,但无济于事。它没有改变任何东西。
  • 这是我的 index.js 和 index.html 代码plnkr.co/edit/pig8u4SwuigRN3ej3KLm

标签: javascript jquery html express socket.io


【解决方案1】:

上面的代码好像在后端,对吗?

尝试以下方法,必要时根据您的需要进行调整:

io.on('connection', function (socket) {
    // You should expect ONLY one user connected, 
    // > otherwise, you're creating multiple sessions :)
    console.log('a user connected');
    socket.on('join room', function (data) {
        var room = data.room;
        console.log('Room: ', room);
        var msg = "<span style='color:darkgreen;'>" + data.user + " has joined chat.</span>";

        socket.join(room); // No callback needed
        console.log(socket.id + " now in rooms ", socket.rooms);
        io.to(room).emit('system message', msg);
        // Change it to io.to(room)

    });
});

我注意到您要求使用以下方式加入前端:

$(".channelChange").click( function(evt) {
    var socket = io();
    $("#messages").html("");
    evt.stopPropagation();
    if($.inArray(evt.currentTarget, $(this).children())){
        console.log("user moved to " + evt.currentTarget.id);
    }
    setCookie("currentRoom", evt.currentTarget.id, 1);
    $(".roomName").html("<span class='3Dtext'>" + evt.currentTarget.id + "</span>");
    $("#enter-sound").get(0).play();
    getMessages(getCookie("currentRoom"));
    // Here you ask to join room
    socket.emit('join room', { user: getCookie("username"), room: getCookie("currentRoom") });
})

并收到系统消息

   $(function(){
        var socket = io();
        socket.on('system message', function(msg) {
            alert("test");
            $('#messages').append($('<div class="systemMessage">').html(msg));
            var height = $("#messages")[0].scrollHeight;
            $.mobile.silentScroll(height);
    });

您将看到的主要问题是您每次都调用io(),这会创建不同的会话, 1. 会话一加入房间 2. 一个不同的会话将等待系统消息

因此,您需要一个 io() 会话,一个快速的工作是创建一个自调用函数:

const setIo = (function (){
        const _io = io();
        return () => _io;
    })()

然后将所有 io() 声明替换为:var socket = setIo();

如:

$(".channelChange").click( function(evt) {
    var socket = setIo();
    $("#messages").html("");
    evt.stopPropagation();

这将创建一个 io() 会话而不是不同的会话,并在您每次调用 setIo() 时重新使用它

您最终会看到弹出的警报:

【讨论】:

  • 我想我可能会看到发生了什么。这是 console.log 返回的内容,用于显示套接字所在的房间:gp187Mc6-75VmnTsAAAf now in rooms { 'gp187Mc6-75VmnTsAAAf': 'gp187Mc6-75VmnTsAAAf', 'General Chat': 'General Chat' }
  • 是的,刚刚发现问题所在,搞定了,给我 5 分钟
  • 问题是你多次调用 io() ,每次调用都会创建一个新的套接字会话,因此,它们对每个事件的逻辑是独立的。使用自调用函数来解决它。
  • 成功了!我从来没有想过这对 socket.io 来说是新的。太感谢了!现在我只需要玩弄设计部分,让它附加在底部。再次感谢!
【解决方案2】:

socket.join() 是异步的。当你试图发送到房间时它还没有完成,所以没有消息进入那个套接字,因为它还没有在房间里。所以,改变这个:

socket.join(room, function () {
    console.log(socket.id + " now in rooms ", socket.rooms);
});

io.in(room).emit('system message', msg);

到这里:

socket.join(room, function () {
    console.log(socket.id + " now in rooms ", socket.rooms);
    io.in(room).emit('system message', msg);
});

因此,在这个新版本中,您要等到 .join() 完成之后而不是之前才发送到房间。

您可以在socket.io doc here 中看到类似的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 2019-03-12
    • 2017-09-27
    • 1970-01-01
    • 2021-01-04
    • 2021-09-04
    • 2013-08-20
    • 1970-01-01
    相关资源
    最近更新 更多