简体   繁体   中英

Socket.io handle receiving synchronously

For some reason, socket.io is being such a pain when it comes to this. I've been at this problem for around an hour and their is not much information anywhere online, because JavaScript is synchronous it is really hard to find information on this event.

So basically I'm receiving disconnect's in socket.io like any other programmer would, as such:

client.on('disconnect', function() {
    console.log("Client left");
    removeClient(client);
    console.log("Client completely removed");
  });

Now, here is the problem. Users disconnect and it works fine, unless of course multiple users disconnect right after eachother. I used debug messages and this is what's happening.

Scenario: We have two users leaving at the same time. When a user leaves, it runs 5 different functions on the server.

USER1 leaves:

function 1.
function 2.
function 3.
USER2 LEAVES:
function 1.
function 2.
function 3.
function 4.
function 5.
User 2 has successfully completely left
function 4.
function 5.
User 1 has successfully completely left

Problem: For some reason while user 1 is being removed, it will receive a disconnect from user 2 then start removing user 2. I'm trying to make it so that if user 2 disconnects while the server is removing user 1, it will wait until the 5 functions for user 1 are completed before executing them for user 2.

Edit: the title says "receiving" rather than disconnects because it will do this for any event.

It's pretty hard to suggest a code fix when you don't show the relevant code, but if according to your comment, the issue is that your array gets changed out from under you while you're in the middle of iterating on it, then the typical way to handle that is to make a temporary copy of the array for purposes of iterating it . Your copy won't get changed then. If you need to check if a socket might have been already removed from the original array, then you can check for that too.

Here's the idea:

// suppose your array of sockets is in socketList

// make a copy of the sockets array
var copyList = socketList.slice(0);
var socket;

for (var i = 0; i < copyList.length; i++) {
    socket = copyList[i];
    // make sure this socket is still in the original array
    if (socketList.indexOf(socket) !== -1) {
        // do your operation here on socket
    }
}

If you're using an object instead of an array to store your list of sockets, then you can prefetch the keys with Object.keys() and iterate those keys, checking to see if the key is still in the object when it comes time to process it.

FYI, I haven't proven this myself, but the MDN documentation for .forEach() suggests that using it to iterate an array is also safe from concurrent modifications. Since we don't have the exact code, I don't know exactly how it behaves so I'd probably rather use my own copy as above.

A possible cause of this could also be that you have async code which is infact running synchronously. This means that you have to go up and down the call stack before any other handlers can be called. You can force the stack to unwind and then resume using process.nextTick but should probably be aware of the performace consequences since I think there is a limit of how many callbacks can happen on one cycle while the rest will queue up.

var callback = function (err, data) {
   // will now be next on the stack
   process.nextTick(function() {
        // will be on a clean(ish) stack
   });
}
a(callback); // should be async but is sync 

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