Обратные вызовы в 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.