Что стоит за асинхронностью в Javascript - система, управляемая событиями - PullRequest
2 голосов
/ 21 мая 2011

, пожалуйста, помогите мне понять это.

У вас есть функция, которая вызывает несколько методов:

function() {
   methodA(function(){...});
   methodB();
   methodC();
}

Из языков, в которых нет обратных вызовов или анонимных функций, я привык кфакт, что выполнение не продолжается до тех пор, пока метод не вернется.

Так что если бы я вызвал methodA с обратным вызовом, выполнение должно было бы ждать, пока метод не вернется, что не будет асинхронным, верно?

Так что, например, я могу сохранить обратный вызов некоторому объекту и получить метод methodA return.Затем выполняются methodB и methodC.И когда пользователь нажимает кнопку, какой-то обработчик выполняет обратный вызов?

Я пришел к выводу, что в javascript нет ничего асинхронного по сравнению с java или python (не в отношении многопоточности) .... потому что в javaобратный вызов не был бы замыканием / анонимным методом, но объектом с методом «execute», и он был бы точно таким же, чуть более сложным ... Конечно, эта система событий JS специфична для DOM

Ответы [ 3 ]

5 голосов
/ 22 мая 2011

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

Из-за этого невозможно определить, когда выполнение обратного вызова впример будет работать по отношению к другим методам (за исключением того, что он не может быть запущен до вызова methodA) - он может быть вызван из methodA или methodB или из щелчка позже, или вообще не вызываться.(Однако, если нет исключения - или одна из функций вызывает одну из других функций - тогда methodA будет выполняться до methodB, что, в свою очередь, будет выполняться до methodC; если methodA вызвало исключениетогда ни methodB, ни methodC не будут вызваны).

Что делает добавить асинхронное поведение является источником асинхронного события , таким как событие таймера или пользовательский интерфейстакие действия, как нажатие кнопки.

Однако важно помнить, что Javascript не поддерживает потоки и не поддерживает их.Javascript должен «остановиться» (выполнение должно возвращаться из функции обратного вызова, вызванной из источника асинхронного события), прежде чем может быть запущено новое асинхронное событие.(Асинхронные события помещаются в очередь [в зависимости от ситуации], поэтому событие таймера не будет «потеряно», если выполнение другого обратного вызова занимает слишком много времени.)

Именно поэтому while (true) {} заставит страницу браузера зависнуть и предотвратитьобработчики событий кнопки не обрабатываются.

Счастливое кодирование.


Примеры случаев ( jsfiddle demo ):

function invokeNow(callback) {
   // nothing asynchronous going on here.
   // the callback is invoked right now and the result is returned.
   return callback()
}
alert(invokeNow(function () { return "Hello world!" }))

function doLater(callback) {
    // setup an asynchronous event
    setTimeout(callback, 1000)
    return "It isn't 'later' yet!"
}

alert(doLater(function () {
    alert("Later!")
    // note that this is running in the callback from the previous
    // timer event. if this code was below the outer alert then
    // it wouldn't have allowed the first timer callback to have occurred
    // until the blocking while was complete
    alert(doLater(function () { alert("I still ran!") }))
    var end = (+new Date) + 4000
    while ((+new Date) < end) { /* wait */ }
    alert("I am done waiting")
}))

Предупреждение: Кажется, что проблема с Firefox 4 (4.0.1) и кодом выше.Хотя это работает, как показано, ожидаемый порядок отличается от фактического порядка, если время ожидания составляет менее 800 мс.Я разместил SO: Асинхронное событие таймера, запущенное синхронно («глючно») в Firefox 4? , так что, надеюсь, будет какое-то разрешение.Поведение работает, как и ожидалось, в Firefox 3, IE 9 и Chrome 11.

1 голос
/ 22 мая 2011
function main() {
   methodA(function callback(){...});
   methodB();
   methodC();
}

Предполагается, что обратный вызов не выполняется немедленно.

Порядок выполнения:

  • methodA
  • methodB
  • methodC
  • ... другие вещи, пока стек не пуст
  • обратный вызов
0 голосов
/ 22 мая 2011

Javascript является последовательным, за исключением случаев, когда вы используете setInterval, setTimeout или делаете запрос к серверу с помощью обратного вызова или onload.Не уверен, что есть другие случаи.

Если у вас есть что-то вроде:

function methodA(fn){
  ...
  fn();
}

Тогда обратный вызов будет вызван, когда вы позвоните methodA(function(){...})

...