У меня сложилось впечатление, что JavaScript всегда был асинхронным. Тем не менее, я узнал, что есть ситуации, когда это не так (например, манипуляции с DOM). Есть ли хорошая ссылка где-нибудь о том, когда он будет синхронным и когда он будет асинхронным? JQuery влияет на это вообще?
javascript
jquery
Брайан
источник
источник
Ответы:
JavaScript всегда синхронный и однопоточный. Если вы выполняете блок кода JavaScript на странице, то никакой другой код JavaScript на этой странице в настоящее время не будет выполняться.
JavaScript является только асинхронным в том смысле, что он может выполнять, например, Ajax-вызовы. Вызов Ajax прекратит выполнение, и другой код сможет выполняться до тех пор, пока вызов не завершится (успешно или нет), после чего обратный вызов будет выполняться синхронно. Никакой другой код не будет запущен в этот момент. Он не будет прерывать любой другой код, который работает в данный момент.
Таймеры JavaScript работают с таким же типом обратного вызова.
Описание JavaScript как асинхронного может вводить в заблуждение. Точнее сказать, что JavaScript является синхронным и однопоточным с различными механизмами обратного вызова.
JQuery имеет опцию для вызовов Ajax, чтобы сделать их синхронно (с
async: false
опцией). У начинающих может возникнуть соблазн использовать это неправильно, потому что это допускает более традиционную модель программирования, к которой можно было бы привыкнуть. Причиной этого является то, что эта опция блокирует весь JavaScript на странице до ее завершения, включая все обработчики событий и таймеры.источник
JavaScript является однопоточным и имеет модель синхронного выполнения. Однопоточный означает, что одна команда выполняется одновременно. Синхронный означает, что по одному, то есть одна строка кода выполняется одновременно для появления кода. Так что в JavaScript одна вещь происходит одновременно.
Контекст выполнения
Движок JavaScript взаимодействует с другими движками в браузере. В стеке выполнения JavaScript есть глобальный контекст внизу, и затем, когда мы вызываем функции, механизм JavaScript создает новые контексты выполнения для соответствующих функций. Когда вызываемая функция выходит, ее контекст выполнения выталкивается из стека, а затем выталкивается следующий контекст выполнения и так далее ...
Например
В приведенном выше коде будет создан глобальный контекст выполнения, и в этом контексте
var one
он будет сохранен, и его значение будет равно 1 ... при вызове вызова xyz () создается новый контекст выполнения, и если мы определили какую-либо переменную в функции xyz эти переменные будут храниться в контексте выполнения xyz (). В функции xyz мы вызываем abc (), а затем создается контекст выполнения abc () и помещается в стек выполнения ... Теперь, когда abc () заканчивает, его контекст извлекается из стека, затем контекст xyz () извлекается из стек, а затем глобальный контекст будет вытолкнут ...Теперь об асинхронных обратных вызовах; асинхронный означает более одного за один раз.
Как и в стеке выполнения, есть очередь событий . Когда мы хотим получить уведомление о каком-либо событии в движке JavaScript, мы можем прослушать это событие, и это событие помещается в очередь. Например, событие запроса Ajax или событие запроса HTTP.
Всякий раз, когда стек выполнения пуст, как показано в приведенном выше примере кода, механизм JavaScript периодически просматривает очередь событий и определяет, есть ли какое-либо событие, о котором следует уведомить. Например, в очереди было два события: запрос ajax и запрос HTTP. Он также проверяет, есть ли функция, которая должна быть запущена для этого триггера события ... Таким образом, механизм JavaScript уведомляется о событии и знает соответствующую функцию для выполнения в этом событии ... Таким образом, механизм JavaScript вызывает функция-обработчик, в данном случае, например, AjaxHandler () будет вызываться и, как всегда, когда вызывается функция, ее контекст выполнения помещается в контекст выполнения, и теперь выполнение функции заканчивается, и запрос ajax события также удаляется из очереди событий. ... Когда AjaxHandler () завершает работу, стек выполнения пуст, поэтому механизм снова просматривает очередь событий и запускает функцию обработчика событий HTTP-запроса, который был следующим в очереди. Важно помнить, что очередь событий обрабатывается только тогда, когда стек выполнения пуст.
Например, посмотрите код ниже, объясняющий стек выполнения и обработку очереди событий движком Javascript.
И
Теперь запустите веб-страницу и нажмите на страницу, и посмотрите результаты на консоли. Выход будет
Механизм JavaScript выполняет код синхронно, как объяснено в части контекста выполнения, браузер асинхронно помещает вещи в очередь событий. Таким образом, функции, выполнение которых занимает очень много времени, могут прерывать обработку событий. Вещи, происходящие в браузере, такие как события, обрабатываются таким образом JavaScript, если есть прослушиватель, который должен работать, механизм запустит его, когда стек выполнения пуст. А события обрабатываются в том порядке, в котором они происходят, поэтому асинхронная часть рассказывает о том, что происходит вне движка, то есть что должен делать движок, когда происходят эти внешние события.
Так что JavaScript всегда синхронен.
источник
JavaScript является однопоточным, и все время вы работаете над нормальным синхронным выполнением потока кода.
Хорошими примерами асинхронного поведения, которое может иметь JavaScript, являются события (взаимодействие с пользователем, результаты запроса Ajax и т. Д.) И таймеры, в основном действия, которые могут произойти в любое время.
Я бы порекомендовал вам взглянуть на следующую статью:
Эта статья поможет вам понять однопотоковую природу JavaScript и то, как таймеры работают внутри и как работает асинхронное выполнение JavaScript.
источник
Кому-то, кто действительно понимает, как работает JS, этот вопрос может показаться странным, однако большинство людей, использующих JS, не имеют такого глубокого понимания (и не обязательно это нужно), и для них это довольно запутанный вопрос, я буду попытаться ответить с этой точки зрения.
JS является синхронным в том, как выполняется его код. каждая строка запускается только после строки до ее завершения, и если эта строка вызывает функцию после завершения, т. д.
Основная путаница возникает из-за того, что ваш браузер может сказать JS извинять больше кода в любое время (аналогично тому, как вы можете извинить больше кода JS на странице из консоли). Например, в JS есть функции обратного вызова, цель которых - позволить JS вести себя асинхронно, чтобы другие части JS могли работать, ожидая, пока выполненная функция JS (IE
GET
вызов) вернет ответ, JS продолжит работать до браузер получает ответ, и в этот момент цикл обработки событий (браузер) выполнит код JS, который вызывает функцию обратного вызова.Поскольку цикл событий (браузер) может вводить больше JS для выполнения в любой точке, в этом смысле JS является асинхронным (основные вещи, которые заставят браузер вводить код JS, - это таймауты, обратные вызовы и события)
Я надеюсь, что это достаточно ясно, чтобы быть полезным для кого-то.
источник
Определение
Термин «асинхронный» может использоваться в несколько ином значении, что приводит к кажущимся противоречивым ответам, тогда как на самом деле это не так. Википедия по асинхронности имеет это определение:
код, отличный от JavaScript, может ставить такие «внешние» события в очередь некоторых событий JavaScript. Но это так далеко.
Нет выкупа
Нет внешнего прерывания выполнения кода JavaScript для выполнения другого кода JavaScript в вашем скрипте. Куски JavaScript выполняются одна за другой, и порядок определяется порядком событий в каждой очереди событий и приоритетом этих очередей.
Например, вы можете быть абсолютно уверены, что никакой другой JavaScript (в том же скрипте) никогда не будет выполняться, пока выполняется следующий фрагмент кода:
Другими словами, в JavaScript нет вытеснения . Что бы ни находилось в очередях событий, обработка этих событий должна будет ждать, пока такой фрагмент кода не завершится. Спецификация EcmaScript говорит в разделе 8.4 Задания и очереди заданий :
Примеры асинхронности
Как уже писали другие, есть несколько ситуаций, когда асинхронность вступает в игру в JavaScript, и она всегда включает в себя очередь событий, которая может привести к выполнению JavaScript только тогда, когда не выполняется другой код JavaScript:
setTimeout()
: агент (например, браузер) поместит событие в очередь событий по истечении времени ожидания. Мониторинг времени и помещения события в очередь происходит с помощью не-JavaScript-кода, и вы можете себе представить, что это происходит параллельно с потенциальным выполнением некоторого JavaScript-кода. Но обратный вызов предоставляетсяsetTimeout
может выполняться только тогда, когда исполняемый в данный момент код JavaScript завершился и соответствующая очередь событий читается.fetch()
: агент будет использовать функции ОС для выполнения HTTP-запроса и отслеживания любого входящего ответа. Опять же, эта задача не-JavaScript может выполняться параллельно с некоторым кодом JavaScript, который все еще выполняется. Но процедура разрешения обещания, которая разрешит возвращаемое обещаниеfetch()
, может выполняться только тогда, когда исполняемый в настоящий момент JavaScript завершен.requestAnimationFrame()
: движок рендеринга браузера (не-JavaScript) поместит событие в очередь JavaScript, когда он будет готов выполнить операцию рисования. Когда обрабатывается событие JavaScript, выполняется функция обратного вызова.queueMicrotask()
: немедленно помещает событие в очередь микрозадач. Обратный вызов будет выполнен, когда стек вызовов пуст и это событие будет использовано.Есть еще много примеров, но все эти функции предоставляются средой хоста, а не ядром EcmaScript. С помощью ядра EcmaScript вы можете синхронно помещать событие в очередь заданий Promise с помощью
Promise.resolve()
.Языковые конструкции
ECMAScript предоставляет несколько языковых конструкций для поддержки шаблона асинхронности, такие как
yield
,async
,await
. Но пусть это не будет ошибкой: никакой код JavaScript не будет прерван внешним событием. «Прерывание» , чтоyield
и ,await
кажется, обеспечивают только контролируемый, предопределена способ возвращения из вызова функции и восстановления его контекста выполнения в дальнейшем, либо JS код (в случаеyield
), или очередь событий (в случаеawait
).Обработка событий DOM
Когда код JavaScript обращается к DOM API, это может в некоторых случаях заставить DOM API вызывать одно или несколько синхронных уведомлений. И если в вашем коде есть обработчик событий, который его прослушивает, он будет вызван.
Это может показаться упреждающим параллелизмом, но это не так: как только ваш обработчик (и) событий вернет (а), DOM API в конечном итоге также вернется, и оригинальный код JavaScript продолжится.
В других случаях DOM API просто отправит событие в соответствующую очередь событий, а JavaScript заберет его после очистки стека вызовов.
Смотрите синхронные и асинхронные события
источник
Синхронно на все случаи.
Пример блокировки потока с помощью
Promises
:Выход будет:
источник