Tamas
Tamas

Reputation: 11214

socket.io - socket.on wait for promise

I have a button that does some communication with the server to check if an entered value (via an input box) already exists. The code is the following:

$("#button").click(function () {
    var exists = false;
    var name = $("#name").val();
    socket.emit("check", name);

    socket.on("checkReturn", function (data) {
        exists = data.result;
    });

    if (exists) {
        console.log("exists")
    } else {
        if (name.length > 0) {
            socket.emit("create", name);
        }
    }
});
});

The problem is that the checkReturn call is asynchronous, and therefore the code carries on without actually waiting for the result. How do I make sure that checkReturn is first finished and only then the rest of the code gets executed?

Upvotes: 9

Views: 22993

Answers (4)

hexacyanide
hexacyanide

Reputation: 91609

Aside from the other answer, you can also use acknowledgements, where a callback is passed between the client and server. Then you can just use the callback of the emit function:

$("#button").click(function() {
  var exists = false; 
  var name = $("#name").val(); 

  socket.emit('check', name, function (data) { 
    exists = data.result;
    if (exists) console.log("exists");
    else (if (name.length > 0) socket.emit("create", name));
  });
});

On the server side it would look like this:

io.sockets.on('connection', function (socket) {
  socket.on('check', function(name, fn) {
    // find if "name" exists
    fn({ exists: false });
  });
});

Upvotes: 14

John
John

Reputation: 6268

You can use socket.io.wait to get synchronous responses from socket.io:

https://www.npmjs.com/package/socket.io.wait

$("#button").click(async function ()
{
    var exists = false;
    var name = $("#name").val();

    let exists = await socket.emitWait("check", name);


    if (exists == true)
    {
        console.log("exists");
    } 
    else
    {
        if (name.length > 0)
        {
            socket.emit("create", name);
        }
    }
});

Upvotes: 1

pvsfair
pvsfair

Reputation: 320

An alternative for @hexacyanide aswer could be done like that:

$("#button").click(async function() {
  var exists = false; 
  var name = $("#name").val(); 

  exists = await new Promise(resolve => socket.emit('check', name, data => resolve(data.result)))

  if (exists) console.log("exists");
  else (if (name.length > 0) socket.emit("create", name));
});

The socket emit is wrapped inside a promisse so it can wait for the callback, and avoid the nesting inside multiple curly braces.

Is not that elegant, but could make your code easier to read if it is encapsulated inside a separated function:

function check(name){
  return new Promise(resolve => socket.emit('check', name, data => resolve(data.result)))
}

And used like such:

$("#button").click(async function() {
  var exists = false; 
  var name = $("#name").val(); 

  exists = await check(name)

  if (exists) console.log("exists");
  else (if (name.length > 0) socket.emit("create", name));
});

Upvotes: 5

Vicky Gonsalves
Vicky Gonsalves

Reputation: 11707

$("#button").click(function () 
{ var exists = false; 
var name = $("#name").val(); 
socket.emit("check", name);

socket.on("checkReturn", function (data) { 
exists = data.result;
if (exists) { console.log("exists") } else { if (name.length > 0) { socket.emit("create", name); } } });    
});

Upvotes: 1

Related Questions