I was following the code snippet here https://github.com/socketio/socket.io-redis#redisadapterclientsroomsarray-fnfunction
io.in('room3').clients((err, clients) => {
console.log(clients); // an array containing socket ids in 'room3'
});
to get the clients in a particular room.
Is there a simple/idiomatic way I can make this snippet synchronous? I want to loop over an array of rooms and synchronously get the count of users clients.length
in each room (ie don’t iterate over the loop until the user count of the current room has been retrieved.)
5
Answers
You can make use of
Promises
andasync await
within afor
loopUsing the above manner will help you iterate over each room and get the clients sequentially one by one.
Although you can’t force them to run synchronously
you can’t force asynchronous things to become synchronous in js. You can execute asynchronous things sequentially though (or in parallel if you wish).
callbacks:
promises without async / await:
with async / await (builds off answer from @Shubham Katri)
or you could make use of either promise based method inside your function that needs the count by declaring it
async
(though this may cause unintended issues in some frameworks):rxjs (external lib but very idiomatic IMO):
and a stackblitz to play with these:
https://stackblitz.com/edit/rxjs-xesqn9?file=index.ts
This works for me
I have something simple and functional, though it uses a library I created so it’s not quite idiomatic. There’s no good way to turn async code into sync code, but this way you don’t have to worry about that kind of thing.
then you would use the function
getTotalClientsCount
on your array of rooms like soif you really wanted to get fancy, you could use a transducer to get the total count of clients in rooms without creating any intermediate arrays
I write a crash course on transducers here
The other answers here seem to overcomplicate things. This can easily be done without any 3rd party libraries.
Wrapping a callback in a Promise gives you more control over the flow of the program.
If you are inside of an async function, you can use await, which will make asynchronous code feel more like synchronous code. (although “top-level await” is supported within modules in modern browsers)
Using for-await is also an option, if you want to start iterating before all promises have resolved: