Подождите, пока событие не вернется - PullRequest
0 голосов
/ 16 октября 2018

У меня есть функция на JavaScript, написанная таким образом, я не могу изменить:

function doSomething() {
    doFirst();
    (...)
}

Первая функция внутри doSomething отправляет пакет через WebSocket и должна ждать ответа, чтобы вернуться.Итак, другими словами, мне нужно doFirst, чтобы дождаться этого ответа, прежде чем делать (...).

В качестве первой идеи я подумал, что мог бы использовать обратные вызовы для вызова (...), когда doFirst завершен, но я не могу этого сделать, потому что Я не могу ничего написать на doSomething , поэтому следующий пример вообще не будет возможен:

function doSomething() {
    doFirst(function() {
        (...)
    });
}

Итак, с этим ограничением я должен иметь возможность написать что-то внутри doFirst (но, опять же, не doSomething), чтобы достичьэто поведение.

Если я просто объявлю обратный вызов onmessage WebSocket, (...) будет выполнено до того, как сокет получит ответ, и если я использую что-то вроде:

while(!received) { } 

Конечно, браузерзависает, и даже если я получу ответ, я не смогу продолжить.

Ответы [ 4 ]

0 голосов
/ 16 октября 2018

Вы можете сделать это, основываясь на обещаниях и ожидающих операторах.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

function doFirst() {
    return new Promise(resolve => {
        setTimeout(() => {
          resolve('do first');
        }, 2000);
      });
    }

    async function doSomething() {
     var received =  await doFirst();
       console.log(received);
    }
0 голосов
/ 16 октября 2018

Опрос, как и ваш while(!received), но со сном, так что EventLoop позволяет другие инструкции между ними.Т.е.:

const checkInterval = setInterval(function(){
  if(!received) return;
  clearInterval(checkInterval);
  //do your stuff here
}, 10)
0 голосов
/ 16 октября 2018

Еще один «возможный» подход, вот основанный на Promise, который все еще опирается на интервал, но изолирует остальную часть кода.

var _onceReceived = function(timeoutSeverity) {
    return new Promise(function(resolve, reject){
    var _mInterval = setInterval(function(){
      if (received !== null && received !== undefined) {
        clearInterval(_mInterval);
        resolve(received);
      }
    }, timeoutSeverity);
  });
}

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

Пример использования:

_onceReceived(1000).then(function(res){
    alert('received was now set, and it is: ' + res);
});

Полный пример:

var received;
function doesSomething() {
    setTimeout(function(){
        received = 10;      
  }, 5000);
}

var _onceReceived = function(timeoutSeverity) {
    return new Promise(function(resolve, reject){
    var _mInterval = setInterval(function(){
        console.log('checking!');
      if (received !== null && received !== undefined) {
        clearInterval(_mInterval);
        resolve(received);
      }
    }, timeoutSeverity);
  });
}

doesSomething();
_onceReceived(1000).then(function(res){
    alert('received was now set, and it is: ' + res);
});

рабочая скрипка: http://jsfiddle.net/m1zs5vcw/1/

0 голосов
/ 16 октября 2018

Я думаю, что традиционное решение flag было бы полезно.Вы можете инициировать переменную flag=False вне doSomething() или doFirst() и сделать ее flag=True, когда получите ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...