3

我正在使用 node.js 和 socket.io 编写一个应用程序,用户可以在其中在个人聊天室中相互交谈。每个人都可以有多个打开的聊天室。当用户想要退出聊天室时,系统必须移除该聊天室的所有套接字监听器。

websocket.on('createRoom', function(roomID) {
    ...
    var room = generateRoom();
    ...

    // Leaving room
    $('#exitButton').on('click', function() {
        // Removes
        websocket.removeAllListeners('createRoom');
    });

    // User joins the room
    websocket.on('main/roomJoin/'+roomID, function(username) {
        alert(username + ' has joined the room');
    });

    ...

    websocket.on('chat/messageReceived/'+roomID, function(message) {
        room.printMessage(message);
    });
});

问题是 removeAllListeners 不会删除内部侦听器,因此如果另一个用户在另一个用户退出后进入房间,他会收到警报。

另一种方法是将听众放在外面,但管理多个房间更难。

谢谢。

4

1 回答 1

6

我知道您已经解决了问题,但无论如何我都会回答,以便人们知道发生了什么。

1) removeAllListeners() 仅删除相关事件的回调数组;它根本不会影响任何其他事件。

当您定义 eventListener (即 on('xyz', function(){})时,您将回调函数附加到由提供的事件名称索引的数组中。在您的情况下,该数组是相关对象的成员"webSocket" 对象 webSocket.on("createRoom", function(){}) 将函数添加到类似于

webSocket.listeners = {
    "createRoom: [ function ],
    "someOtherEvent": [ function, function, function ]
}

webSocket.removeAllListeners('createRoom') 将简单地从对象中删除 createRoom 键及其关联值,而不影响任何其他事件:

webSocket.listeners = { "someOtherEvent": [ function, function, function ] }

2) 虽然 roomJoin 和 messageReceived 事件是在 createRoom 事件的回调函数中定义的,但它们仍然在 webSocket 对象的同一个实例上运行。因此,您最终会得到一个类似于以下内容的 listeners 对象:

webSocket.listeners = {
    "createRoom: [ function ],
    "main/roomJoin: [ function ],
    "chat/messageReceived": [ function ]
}

结合上面第 1 点的信息,webSocket.removeAllListeners('createRoom') 将产生以下结果:

webSocket.listeners = {
    "main/roomJoin: [ function ],
    "chat/messageReceived": [ function ]
}

仅仅因为这两个事件是在另一个事件的回调中定义的,并不意味着它们无论如何都与那个“父”事件相关联。正如您现在所知道的,删除这些侦听器的唯一方法是显式删除它们:

$('#exitButton').on('click', function() {
    // Removes
    websocket.removeAllListeners('createRoom');
    websocket.removeAllListeners('main/roomJoin');
    websocket.removeAllListeners('chat/messageReceived');
});
于 2012-09-17T20:10:38.873 回答