简体   繁体   中英

Socket.io - Cannot send messages to rooms

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);
});

If I change io.in(room) to socket.broadcast the system message goes through. For whatever reason though, it will not send messages to specific rooms, it just does nothing, no errors either. Any ideas what's going wrong here?

It seems the code above is on back-end, correct?

Try the following, adapt it with your needs if necessary:

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)

    });
});

I noticed you're asking to join on front-end using:

$(".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") });
})

And receiving the system message on:

   $(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);
    });

The main problem as you'll see, is that you're calling io() everytime, this created different sessions, 1. Session one joins a room 2. A different session will await for system message

Hence, you need a single io() session, a quick work arround is to make a self invoking function:

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

And then Replace all io() declarations to: var socket = setIo();

such as:

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

This will create a single io() session instead of different ones, and re-use it everytime you call setIo()

You'll eventually see the alert pop up:

在此输入图像描述

socket.join() is asynchronous. It has not completed yet when you're trying to send to the room, so no message goes to that socket because it isn't yet in the room. So, change this:

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

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

to this:

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

So, in this new version you're not sending to the room until AFTER the .join() has completed rather than before.

You can see a similar example right in the socket.io doc here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM