Search code examples
pythonsocketssocket.iotimeoutemit

How to wait for socketIO client to emit


I want to make a function which express server would emit to client (python) and python would do something and emit the result back to server. Server would wait for the client emitted result and return that result to front end. If after sometime, python still hasn't emit something, express server would tell front end that no result was received. Can I use a promise and set timeout to wait for the emit message from python?


Solution

  • Shouldn't be much of a problem. See Acknowledgments in the socket.io docs. They even have an example for a timeout :

    // express server endpoint
    app.get('/somethingcool', (req, res) => {
    
      // assuming socket will be the client socket of the python server
      socket.emit("do_something_i_will_wait", {/* data */}, withTimeout((response) => {
    
        console.log("success!");
        res.status(200).send(response);
    
      }, () => {
    
        console.log("timeout!");
        res.status(500).send("python took to long to reply");
    
      }, 5000));
        
    });
    
    // helper function for timeout functionality
    const withTimeout = (onSuccess, onTimeout, timeout) => {
      let called = false;
    
      const timer = setTimeout(() => {
        if (called) return;
        called = true;
        onTimeout();
      }, timeout);
    
      return (...args) => {
        if (called) return;
        called = true;
        clearTimeout(timer);
        onSuccess.apply(this, args);
      }
    }
    

    How Acknowledgments work

    So we emit something from server to client, something simple, and as last argument we'll put a function - this will be our acknowledgment function.

    // server 
    
    socket.emit("ferret", "tobi", (data_from_client) => {
      console.log(data_from_client); // data will be "woot"
    });
    
    

    On the client side it will look something like this. The callback we set for the event listener "ferret" takes 2 arguments, the data we pass from server to client, and our acknowledgment function.

    // client
    
    client.on("ferret", (name, fn) => {
      fn("woot");
    });
    

    Simplier example

    I understand that the withTimeout example from the socket.io docs can be a bit hard to follow, so here a less complex example, which does the same basically :

    app.get('/somethingcool', (req, res) => {
      
      let got_reply = false;
      
      const timeout = setTimeout(() => {
        if (got_reply) { return; }
        got_reply = true;
        res.status(500).send("too late");
      }, 5000);
    
    
      socket.emit("do_something_i_will_wait", {}, (reply) => {
        if (got_reply) { return };
        got_reply = true;
        clearTimeout(timeout);
        res.status(200).send(reply);
      });
    
    });