Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 301
Tamas Avatar asked Oct 26 '13 16:10

Tamas


People also ask

Does socket IO guarantee order?

socket io relies on websockets and websockets rely on tcp that guarantees that packets will be received in the samr order they are sent.

Is socket emit a promise?

socket. emit() happens to return the socket itself (allows for method chaining). But, that's not relevant here because there's no point in returning any value from a Promise executor function. If you do return a value, it is not used by the Promise in any way.

Is socket IO asynchronous?

JS, Socket.IO enables asynchronous, two-way communication between the server and the client. This means that the server can send messages to the client without the client having to ask first, as is the case with AJAX.


2 Answers

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('ferret', function(name, fn) {
    // find if "name" exists
    fn({ exists: false });
  });
});
like image 88
hexacyanide Avatar answered Sep 19 '22 14:09

hexacyanide


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));
});
like image 33
pvsfair Avatar answered Sep 19 '22 14:09

pvsfair