Как JavaScript обрабатывает ответы AJAX в фоновом режиме? - PullRequest
136 голосов
/ 28 сентября 2011

Поскольку JavaScript выполняется в одном потоке, после выполнения запроса AJAX, что на самом деле происходит в фоновом режиме?Я хотел бы получить более глубокое понимание этого, может кто-нибудь пролить свет?

Ответы [ 3 ]

207 голосов
/ 28 сентября 2011

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

Сеть с собственным кодом, которая находится под вызовом ajax, будет знать, когда будет выполнен ответ ajax, и событие будет добавлено в очередь событий javascript. То, как нативный код знает, когда выполняется вызов ajax, зависит от реализации. Он может быть реализован с помощью потоков или может быть сам по себе управляемым событиями (это на самом деле не имеет значения). Суть реализации заключается в том, что когда ответ ajax завершен, некоторый нативный код узнает, что он выполнен, и поместит событие в очередь JS.

Если в данный момент не запущен Javascript, событие будет немедленно запущено, что запустит обработчик ответа ajax. Если что-то выполняется в то время, то событие будет обработано, когда закончится текущий поток выполнения javascript. Там не должно быть никакого опроса с помощью движка JavaScript. Когда часть Javascript завершает работу, движок JS просто проверяет очередь событий, чтобы увидеть, есть ли что-то еще, что нужно запустить. Если это так, он выталкивает следующее событие из очереди и выполняет его (вызывая одну или несколько функций обратного вызова, которые зарегистрированы для этого события). Если в очереди событий ничего нет, то у интерпретатора JS есть свободное время (сборка мусора или бездействие) до тех пор, пока какой-либо внешний агент не поместит что-то еще в очередь событий и не разбудит его.

Поскольку все внешние события проходят через очередь событий, и ни одно событие не запускается, пока javascript фактически выполняет что-то еще, он остается однопоточным.

Вот несколько статей о деталях:

16 голосов
/ 05 октября 2011

Вы можете найти здесь очень полную документацию по обработке событий в javascript.
Он написан парнем, работающим над реализацией javascript в браузере Opera.

Точнее, посмотрите на заголовки: «Поток событий», «Очередь событий» и «Непользовательские события»: вы узнаете, что:

  1. Javascript запускается в одном потоке для каждой вкладки или окна браузера.
  2. События ставятся в очередь и выполняются последовательно.
  3. XMLHttpRequest запускается реализацией, а обратные вызовы запускаются с использованием очереди событий.

Примечание. Исходная ссылка: ссылка , но теперь она не работает.

0 голосов
/ 07 марта 2019

Я хочу немного подробнее рассказать о реализации ajax, упомянутой в ответах.

Хотя (обычное) выполнение Javascript не многопоточное - как хорошо отмечено в ответах выше - однако , реальная обработка AJAX responses (а также обработка запросов) - это , а не Javascript, и он - обычно - является многопоточным. (см. реализацию источника хрома XMLHttpRequest, о которой мы поговорим выше)

и я объясню, давайте возьмем следующий код:

var xhr = new XMLHttpRequest();

var t = Date.now;
xhr.open( "GET", "https://swx.cdn.skype.com/shared/v/1.2.15/SkypeBootstrap.min.js?v="+t(), true );

xhr.onload = function( e ) {
		console.log(t() + ': step 3');
    
    alert(this.response.substr(0,20));
};
console.log(t() + ': step 1');
xhr.send();
console.log(t() + ': step 2');

after an AJAX request is made (- после шага 1), затем, пока ваш js-код продолжает выполняться (шаг 2 и после), браузер начинает реальную работу: 1. форматирования tcp-запроса 2. открытия сокета 3. отправки заголовков 4. рукопожатия 5. отправки тела 6. ожидания ответа 7. чтение заголовков 8. чтение тела и т. д. вся эта реализация обычно выполняется в другом потоке параллельно с выполнением вашего кода js. Например, в упомянутой реализации Chromium используется Threadable Loader go digg-in ? (вы также можете получить некоторое впечатление, посмотрев на вкладку сети загрузки страницы, вы увидите некоторые одновременные запросы).

В заключение я бы сказал, что, по крайней мере, большинство ваших операций ввода-вывода могут выполняться одновременно (и вы можете воспользоваться этим, например, с помощью await ). но все взаимодействие с этими операциями (выдача, выполнение обратного вызова js) все синхронно.

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