Можно ли пропустить асинхронное событие в JS, если вы подпишетесь на него после того, как запросите его запуск? - PullRequest
1 голос
/ 07 августа 2011

Вот простой отрывок для выполнения Ajax-запроса

var req = new XMLHttpRequest();
req.open('GET', 'http://www.mozilla.org/', true);
req.send(null); // First - send the request
// Then bind for the "result"
req.onreadystatechange = function (e) {
    if (req.readyState == 4 && req.status == 200) {
        // ...
    }
};

Что я здесь делаю:

  1. Отправка Ajax-запроса.
  2. А затемпривязка для обратного вызова результата.

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

Но в коде на основе реактора это будет работать так, как ожидалось, все время, так как реактор не будет работать до тех пор, пока весь мой код не завершит работу для этой итерации.

Как обстоят дела в браузерах?Было ли это где-то задокументировано?

Не обращайте внимания на тот факт, что Ajax-запрос медленный, и на практике это может никогда не произойти.Я просто привожу это в качестве асинхронного примера (подумайте, websocket, если ajax слишком медленный для вас).

Ответы [ 4 ]

2 голосов
/ 07 августа 2011

JavaScript не является многопоточным в этом смысле. После того как вы сказали .send (null), вы завершите выполнение текущего блока кода, который включает в себя onreadystatechange, и только после этого будут запущены события. Ваш код не будет прерван между этими двумя предложениями для запуска события - событие будет добавлено в очередь событий (буферизирована, если хотите), и когда будет время, событие сработает, вызывая все связанные с ним обработчики. , Он должен вызывать обработчики, которые были добавлены между созданием объекта XMLHttpRequest и запуском события.

По крайней мере, это моя интерпретация проблемы. Для получения дополнительной информации посетите Синхронизация и синхронизация в Javascript , на dev.opera.

2 голосов
/ 07 августа 2011

Теоретически нет, запуск обработчиков событий должен происходить в очереди событий, поэтому он должен происходить во временном интервале после завершения текущего временного интервала, что будет означать, что req.onreadystatechange = ... происходит перед обработкой любых событий. См. javascript - проблемы, связанные с событиями и параллелизмом? , чтобы понять модель параллелизма JavaScript (по крайней мере, в браузере).

На практике Firefox имел (возможно, все еще имел) ошибку, в которой событие onreadystatechange, в частности, запускалось одновременно с очередью событий кадра, чей объект XMLHttpRequest использовался для отправки запроса. У меня появилась привычка к тому, чтобы мои onreadystatechange обработчики выполняли setTimeout(0, ...), чтобы удостовериться, что я не получил неприятных чередований в Firefox.

Также возможно, если вы используете XMLHttpRequest кросс-кадр объекта, как в new otherWindow.XMLHttpRequest(...), потому что тогда ответ может быть обработан в очереди событий другого кадра до того, как закончится текущий временной интервал (в очереди событий этого кадра).

1 голос
/ 07 августа 2011

Теоретически это возможно.

Чтобы избежать этого, поставьте req.onreadystatechange = ... перед req.send(null);.

1 голос
/ 07 августа 2011

Можно ли пропустить асинхронное событие в JS, если вы подпишетесь на него после того, как запросите его запуск?

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

Событие происходит в любом случае .Когда это произойдет, будут вызваны все обработчики, которые зарегистрированы в данный момент времени.

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