Как избежать условий гонки при назначении пользовательских методов WebSocket? - PullRequest
0 голосов
/ 28 ноября 2018

Когда я просматриваю учебные пособия / документацию по WebSockets, я нахожу код вроде this :

var ws = new WebSocket("ws://localhost:8765/dlt");
ws.onopen = () => {
  // do some very important stuff after connection has been established
  console.log("onopen");
}

Но как насчет условий гонки здесь?Чего-то избежать в JavaScript?

Например, этот код (который просто присваивает onopen после соединения было открыто) завершится ошибкой:

var ws = new WebSocket("ws://localhost:8765/dlt");
setTimeout(() => {
  ws.onopen = () => {
    // do some very important stuff after connection has been established
    console.log("onopen"); ///  <== won't be called
  }
}, 100);

МожетЯ уверен , что назначение было выполнено до установления соединения?

(Я пытался расширить WebSocket с помощью пользовательского onopen() метода, но, похоже, это не работает)

class MyWebSocket extends WebSocket {
  onopen() {
    console.log("onopen()");
    /// do some very important stuff after connection has been established
  }
}

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Вы должны прочитать о цикле событий javascript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Event_loop

Если вы посмотрите раздел о Run-to-completion, вы получите это полезное объяснение:

Каждое сообщениеобрабатывается полностью перед обработкой любого другого сообщения.Это дает некоторые приятные свойства при рассуждении о вашей программе, в том числе тот факт, что всякий раз, когда функция запускается, она не может быть перегружена и будет выполняться полностью до запуска любого другого кода (и может изменять данные, которыми манипулирует функция).Это отличается от C, например, где, если функция выполняется в потоке, она может быть остановлена ​​в любой момент системой выполнения для запуска другого кода в другом потоке.

Так в вашем примереприсваивание ws.onopen должно быть завершено до того, как веб-сокет сделает что-то асинхронное по своей природе.Помещая ваше назначение в setTimeout, вы перемещаете его за пределы текущего запущенного контекста, и поэтому оно может не выполняться, пока этого не потребует веб-сокет.


Правда, веб-сокет apiопределенно сбивает с толку и мог бы быть разработан более интуитивным способом.

0 голосов
/ 28 ноября 2018

Вы должны быть уверены, что пример в порядке.Цикл событий Javascript завершит текущую задачу перед выполнением любых других задач.Это означает, что 1) WebSocket не может открыть соединение (асинхронная операция) до события onopen, 2) обработчик события onopen будет вызываться в течение следующих циклов.

Установка времени ожидания для другогоРука усложнит ситуацию, потому что события будут вызываться в каком-то порядке после текущей задачи.Это означает, что у WebSocket есть шанс открыть соединение до того, как был установлен обработчик.

...