Предположим, что какой-то другой метод JavaScript с именем myFunction
вызывается на моей странице, когда myCallback
вызывается асинхронно.
Принимает ли одна операция приоритет над другой?Они оба бегут одновременно?Что происходит?
JavaScript в браузерах однопоточный (исключая использование веб-работников , и синтаксис для этого явный).Так что myFunction
будет работать до тех пор, пока не вернется - с некоторыми оговорками (продолжайте читать).Если уровень ajax завершает операцию , когда myFunction
работает (что вполне возможно) и ему необходимо вызвать обратный вызов, этот вызов получает в очереди .В следующий раз, когда ваш код сработает, будет запущен следующий вызов в очереди.
Может показаться, что нам никогда не придется беспокоиться о состоянии гонки.Это в основном верно, но есть тонкости.Например, рассмотрим следующий код:
var img = document.createElement('img');
img.src = /* ...the URL of the image... */;
img.onload = function() {
// Handle the fact the image loaded
foo();
};
doSomethingElse();
doYetAnotherThing();
Поскольку JavaScript в браузерах является однопоточным, я гарантированно получу событие load
при загрузке изображения, верно?
Неверно.
Код JavaScript является однопоточным, но остальная часть среды, вероятно, нет.Таким образом, может случиться так, что, установив img.src
, браузер может увидеть, что у него есть кэшированная копия изображения, которое он может использовать, и поэтому он вызывает событие load
на img
между строка img.src = ...
и строка img.onload = ...
.Поскольку мой обработчик еще не подключен, я не получаю вызов, потому что к тому времени, когда я подключил свой обработчик, событие уже сработало.
Но вы можете увидеть эффект очереди, если мыпереверните эти строки:
var img = document.createElement('img');
img.onload = function() {
// Handle the fact the image loaded
foo();
};
img.src = /* ...the URL of the image... */;
doSomethingElse();
doYetAnotherThing();
Теперь я перехватываю событие перед настройкой src
.Если событие возникает между строкой img.src = ...
и строкой doSomethingElse
(поскольку изображение хранится в кэше браузера), обратный вызов моего обработчика получает в очереди .doSomethingElse
и doYetAnotherThing
запускаются раньше, чем мой обработчик.Только когда управление выходит из моего кода, вызов в очередь моего обработчика наконец запускается.Код JavaScript является однопоточным, но среда - нет.
Вы также можете уступить среде хоста неочевидными способами.Например, вызывая alert
или его дыхание confirm
, prompt
и т. Д. Эти функции торчат, как больные пальцы в современном JavaScript, потому что они не управляются событиями ;вместо этого выполнение JavaScript приостанавливается, пока отображается модальное окно.Но, как bobince указывает на его подробное обсуждение здесь , это не означает, что ни один из ваших других кодов не будет работать, пока этот модал показывает.Он все еще однопоточный, но один поток приостанавливается в одном месте (модально) и используется для запуска кода в другом месте в это время;действительно очень хорошее различие.(Боб также указывает на некоторую обработку событий - его пример focus
- который, кажется, нарушает это правило, но это не так. Его пример вызывает focus
, который, в свою очередь, вызывает обработчики событий, изатем возвращается, ничем не отличаясь от того, что вы вызываете своими собственными функциями.) Ключевым моментом, который имеет общий элемент, на который указывает Боб, является то, что ваш код вызвал что-то в среде хоста, которая уходит и делает что-то (показывает модальное диалоговое окно,пожары blur
и focus
, обработчики и т.в пользу более современных методов (которые также могут выглядеть примерно в 18 раз лучше).
Так что это предостережения, упомянутые в начале ответа.И, в частности, если myFunction
вызывает alert
, по крайней мере в Firefox обратный вызов завершения ajax будет запускаться во время alert
(не будет в большинстве других браузеров).Если вам интересно узнать, что происходит, а что не происходит во время alerts
и т. Д., , вот тестовая страница , проверяющая setTimeout
и ajax;Вы можете расширить тесты, чтобы пойти дальше.