2010-01-10 3 views
141

У меня создалось впечатление, что JavaScript всегда был асинхронным. Однако я узнал, что есть ситуации, когда это не так (т. Е. Манипуляции с DOM). Есть ли хорошая ссылка где угодно, когда она будет синхронной и когда она будет асинхронной? Действительно ли jQuery влияет на это?Когда JavaScript синхронно?

+10

Всегда за исключением ajax. – defau1t

+0

Принятый ответ неправильный, и вводит в заблуждение, любезно проверьте его. –

ответ

187

JavaScript всегда синхронны и однопоточных. Если вы выполняете блок кода JavaScript на странице, тогда никакой другой JavaScript на этой странице в настоящее время не будет выполнен.

JavaScript является только асинхронным в том смысле, что он может совершать, например, Ajax-вызовы. Код прекратит выполнение, пока вызов не вернется (успешно или иначе), после чего обратный вызов будет выполняться синхронно. На данный момент никакой другой код не будет запущен. Он не будет прерывать какой-либо другой код, который в настоящее время запущен.

Таймеры JavaScript работают с таким же обратным вызовом.

Описание JavaScript как asynchronous, возможно, вводит в заблуждение. Точнее сказать, что JavaScript является синхронным и однопоточным с различными механизмами обратного вызова.

У jQuery есть опция для вызовов Ajax, чтобы сделать их синхронно (с опцией async: false). У начинающих может возникнуть соблазн использовать это неправильно, потому что он позволяет использовать более традиционную модель программирования, к которой можно было бы привыкнуть больше. Причина, по которой это проблематично, заключается в том, что этот параметр будет блокировать все JavaScript на странице, пока она не завершится, включая все обработчики событий и таймеры.

+28

Извините, я не совсем понял это утверждение: «Код перестанет выполняться до тех пор, пока вызов не вернется (успешно или с ошибкой)». не могли бы вы уточнить.Как это утверждение может быть истинным, когда вы также говорите: «Он не будет прерывать любой другой код, который работает»; Вы говорите о коде callbacks только в первом заявлении? Пожалуйста, просветите меня. – krishna

+0

Также обратите внимание. [Является ли javascript гарантированно однопоточным?] (Http://stackoverflow.com/q/2734025/1048572) - ответ № – Bergi

+2

В Nettuts есть учебник, который довольно хорошо объясняет основы асинхронизации здесь : http://net.tutsplus.com/tutorials/javascript-ajax/event-based-programming-what-async-has-over-sync/ – RobW

89

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

Хорошие примеры асинхронного поведения, которое могут иметь JavaScript, - это события (взаимодействие с пользователем, результаты запроса Ajax и т. Д.) И таймеры, в основном действия, которые могут произойти в любое время.

Я бы порекомендовал вам взглянуть на следующей статье:

Эта статья поможет вам понять однопоточных характер JavaScript и как таймеры работают внутри и как работает асинхронное выполнение JavaScript.

async http://ejohn.org/files/427px-Timers.png

119

JavaScript однопоточный и имеет синхронную модель исполнения. Одиночная резьба означает, что одна команда выполняется за один раз. Синхронный означает один за раз, то есть одна строка кода выполняется в момент, когда появляется код. Таким образом, в JavaScript одно происходит одновременно.

Контекст выполнения

двигатель JavaScript взаимодействует с другими двигателями в браузере. В стеке выполнения JavaScript есть глобальный контекст внизу, а затем, когда мы вызываем функции, механизм JavaScript создает новые контексты выполнения для соответствующих функций. Когда вызываемая функция выходит из контекста выполнения, она выставляется из стека, а затем вызывается следующий контекст выполнения и так далее ...

Например

function abc() 
{ 
    console.log('abc'); 
} 


function xyz() 
{ 
    abc() 
    console.log('xyz'); 
} 
var one = 1; 
xyz(); 

В приведенной выше коде будет создан глобальный контекст выполнения и в этом контексте var one будет сохранен, и его значение будет 1 ... когда хуг() вызов называется то будет создан новый контекст выполнения, и если бы мы определили любую переменную в xyz-функции, эти переменные были бы сохранены в контексте выполнения xyz(). В функции xyz мы вызываем abc(), а затем создается сценарий выполнения abc() и помещаем его в стек выполнения ... Теперь, когда abc() завершает свой контекст, выставляется из стека, тогда контекст xyz() вызывается из стек, а затем глобальный контекст ...

Теперь об асинхронных обратных вызовах; асинхронный означает более одного за раз.

Как и в стеке выполнения, есть Event Queue. Когда мы хотим получить уведомление о каком-либо событии в движке JavaScript, мы можем прослушать это событие, и это событие помещается в очередь. Например, событие запроса Ajax или событие HTTP-запроса.

Всякий раз, когда стек выполнения пуст, как показано в приведенном выше примере кода, механизм JavaScript периодически смотрит в очередь событий и видит, есть ли какое-либо событие для уведомления. Например, в очереди было два события, ajax-запрос и HTTP-запрос. Он также смотрит, есть ли функция, которая должна быть запущена в этом триггере событий ... Поэтому механизм JavaScript уведомляется о событии и знает, какая функция должна выполняться в этом событии ... Поэтому механизм JavaScript вызывает функции обработчика, в примерном случае, например AjaxHandler() будет вызываться и, как всегда, когда функция вызывается, ее контекст выполнения помещается в контекст выполнения, и теперь выполнение функции завершается, и запрос ajax события также удаляется из очереди событий ... Когда AjaxHandler() завершает исполняемый стек пуст, поэтому движок снова смотрит в очередь событий и запускает функцию обработчика событий HTTP-запроса, которая была следующей в очереди. Важно помнить, что очередь событий обрабатывается только тогда, когда стеки исполнения пустые.

Например, см. Приведенный ниже код, объясняющий выполнение стека и обработку очереди событий механизмом Javascript.

function waitfunction() { 
    var a = 5000 + new Date().getTime(); 
    while (new Date() < a){} 
    console.log('waitfunction() context will be popped after this line'); 
} 

function clickHandler() { 
    console.log('click event handler...'); 
} 

document.addEventListener('click', clickHandler); 


waitfunction(); //a new context for this function is created and placed on the execution stack 
console.log('global context will be popped after this line'); 

И

<html> 
    <head> 

    </head> 
    <body> 

     <script src="program.js"></script> 
    </body> 
</html> 

Теперь запустите веб-страницу и нажмите на странице, и увидеть выход на консоли. Вывод будет

waitfunction() context will be popped after this line 
global context will be emptied after this line 
click event handler... 

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

Таким образом, JavaScript всегда синхронно.

+11

Этот ответ очень ясен, он должен получить больше оборотов. –

+4

Конечно, лучшее объяснение асинхронного поведения Javascript, которое я прочитал. –

+1

Хорошее объяснение контекста выполнения и очереди. –

Смежные вопросы