Как дождаться, пока клиент SocketIO выдаст

#python #sockets #socket.io #timeout #emit

Вопрос:

Я хочу создать функцию, которую экспресс-сервер будет выдавать клиенту (python), а python что-то сделает и выдаст результат обратно на сервер. Сервер будет ждать результата, выданного клиентом, и вернет этот результат интерфейсу. Если через некоторое время python все еще что-то не выдаст, экспресс-сервер сообщит интерфейсу, что результат не получен. Могу ли я использовать обещание и установить тайм-аут для ожидания сообщения об отправке от python?

Комментарии:

1. Привет и добро пожаловать в SO ! Пожалуйста, включите какой-нибудь код о том, что вы уже пробовали !

Ответ №1:

Это не должно быть большой проблемой. См.Подтверждения в сокете.документы ввода-вывода. У них даже есть пример для тайм-аута :

 // 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);
  }
}
 

Как работают подтверждения

Поэтому мы передаем что — то от сервера клиенту, что-то простое, и в качестве последнего аргумента мы поставим функцию-это будет наша функция подтверждения.

 // server 

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

 

На стороне клиента это будет выглядеть примерно так. Обратный вызов, который мы устанавливаем для прослушивателя событий «хорек», принимает 2 аргумента, данные, которые мы передаем с сервера клиенту, и нашу функцию подтверждения.

 // client

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

Более простой пример

Я понимаю, что withTimeout пример из сокета.документы ввода-вывода могут быть немного сложными для понимания, поэтому приведем менее сложный пример, который в основном делает то же самое :

 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);
  });

});
 

Комментарии:

1. Большое вам спасибо! это выглядит многообещающе! намеренный каламбур!

2. Так, скажем, клиентский сокет будет выдавать sth обратно на сервер. Где я должен поместить socket.on(«ответ от python», данные=> данные))?

3. В этом нет необходимости Acknowledgments . Если вы emit «do_something_i_will_wait», вы также передаете функцию, которая используется в качестве подтверждения. Эта функция подтверждения вызывается, когда клиент отвечает. Нет необходимости добавлять дополнительного слушателя только для ответа. Я добавлю пример того, как это будет выглядеть на стороне клиента.