nickcoding2
nickcoding2

Reputation: 284

How to wait until io.to().emit() is finished in Javascript

I have a function that needs to wait for an io.to().emit() call to finish on the client side before continuing.

I've tried implementations with Promises to try and use await with the function:

await io.to(socketID).emit("request", { var1: val1, var2: val2 })

I think it doesn't work because there's still no way to wait for the io.to().emit() before resolving. Not sure what standard practice for this really is because acknowledgements are only available to socket instances, not the io instance.

const ioEmitFunction = function(id, object) {
  return new Promise(resolve => {
      io.to(id).emit("request", object);
      resolve("Resolved")
  })
}

ioEmitFunction(socketID, { var1: val1, var2: val2 }).then((value) => {
  //callback here after this stuff is done
})

I've also tried implementing custom callbacks...this also doesn't seem to work as intended because there's no way of continuing the function when the "request" emission is finished on the client side. Not sure what exactly I'm supposed to do here, any help is much appreciated!

Upvotes: 0

Views: 936

Answers (1)

jfriend00
jfriend00

Reputation: 707158

You cannot use io.to(...).emit(...) as it does not support acknowledgement. Instead, you will have to send the messages individually with acknowledgement and count the acknowledgements so you know when they have all been received. You will probably also need to implement some sort of timeout because if a raspberry Pi is temporarily down or disconnected, you may not get an acknowledgement for a very, very long time.

In the latest version of socket.io, if you just have one socket, you're trying to do this with, you can get that one socket like this:

const sockets = await io.in(socketId).fetchSockets();
if (sockets.length) {
    // should only be one socket in the array since we used a single socketId as the room indicator
    const piSocket = sockets[0];
    piSocket.emit(msg, data, (response) => {
        // response has been received
    });
}

You could, of course, wrap this in a promise if that was helpful for the control flow. And, you should probably add a timeout.


If this app is pretty much hard-coded to only use one Pi socket, you could also just stuff the Pi socket object into a module-level variable anytime it connects and then you'd already have the Pi socket object available anywhere in that module. It appears you may already be doing that with the socketID.

Upvotes: 1

Related Questions