Давайте проясним некоторые вещи, в то, что вы сказали:
Я новый (2 дня !!) в мире JavaScript и моим единственным предварительного кодирования опыт в Java, где выполнение операторов происходит последовательно. Я понимаю, что, или, по крайней мере, я читал, что JavaScript является асинхронным, что означает, что если есть инструкция, которая принимает длительное время для выполнения, то следующий оператор выполняется без сохранения программы для первого оператора.
Это не то, как это работает. Данная функция является либо асинхронной, либо ее синхронной по дизайну.Он не имеет абсолютно никакого отношения к тому, сколько времени требуется для выполнения. У вас может быть очень быстрая функция async или очень длинная синхронная функция. Что определяет, является ли функция асинхронной или нет, как она разработана. Если он использует асинхронные входы/выходы или таймеры или любую другую асинхронную инфраструктуру, то по меньшей мере часть выполнения функции является асинхронной. Это означает, что некоторые из функций закончат LATER, а некоторые из кода сразу после этого вызова функции будут выполняться до того, как закончится асинхронная часть.
я наткнулся на обратные вызовы (на самом деле очень много !!), но я не мог видеть, как они могут быть использованы для определения порядка выполнения. Я написал фрагмент кода , чтобы понять, как это можно сделать, и я уверен, что смогу использовать некоторую помощь .
Обратные вызовы используются для уведомления вызывающего кода при завершении какой-либо асинхронной операции. Это можно использовать для использования результата асинхронной операции или может использоваться для выполнения следующей части кода, которая должна запускаться последовательно после завершения операции async.
В вашем примере кода, если вы хотите получить нужную последовательность, вы должны вызвать обратный вызов внутри обратного вызова setTimeout()
, чтобы он вызывался после того, как setTimeout()
вызвал выполнение, что дает вам желаемую последовательность.
Вы также должны удалить аргумент callback
для обратного вызова setTimeout
. Этот обратный вызов не передается с этим аргументом, поэтому объявление его там просто неверно. Его можно получить непосредственно из родительской функции через замыкание, как показано здесь:
console.log("Beginning");
function Test(callback){
setTimeout(function(){
console.log("Something that is asynchronous");
// call the callback here to indicate to the calling code
// that the asynchronous operation is now complete
callback();
},5000);
console.log("After Setting Timer");
}
function tstCallBack(){
console.log("Should come last");
}
Test(tstCallBack);
Это будет генерировать последовательность в консоли:
Начиная
После установки таймера
Что-то, что является асинхронным
Должно наступить последнее
Концептуально, двигатель Javascript работает один поток, и что один поток использует очередь событий. Итак, в вашей функции выше, это то, что происходит.
- Выполнено первое
console.log("Beginning");
.
Test(tstCallback)
называется.
- В рамках выполнения функции
Test()
запланирован таймер. Это регистрирует таймер, встроенный в JS-движок.
- Выполнение кода в
Test()
продолжается, console.log("After Setting Timer");
выполняется, а затем эта функция заканчивается.
- Текущий поток выполнения JS завершается, и если в очереди событий нет ничего другого, то JS-движок не имеет ничего общего, но ждать следующего события.
- Спустя некоторое время (5 секунд, когда установлен таймер) внутренний таймер срабатывает, и он помещает событие таймера в очередь событий JS.
- Поскольку в настоящий момент другого действия JS нет, событие таймера вытаскивается из очереди событий и выполняется. Это означает, что вызывается исходный обратный вызов, который был зарегистрирован для таймера.
- Когда вызывается обратный вызов таймера, он выполняет линию
console.log("Something that is asynchronous");
, а затем вызывает callback()
.
- Затем вызывается функция
tstCallback
и выполняется console.log("Should come last");
.
- Событие async завершает выполнение, а механизм JS смотрит, есть ли в очереди событий больше событий. Если это так, следующее событие вытягивается из очереди и запускается.
Есть ряд очень хороших ссылок о том, как Javascript обрабатывает асинхронные операции:
How does JavaScript handle AJAX responses in the background?
How Javascript Timers Work
Do I need to be concerned with race conditions with asynchronous Javascript?
«JavaScript является асинхронным, что означает, что если есть заявление, которое занимает много времени, чтобы xecute, следующий оператор выполняется, не поддерживая программу для первого оператора. " Это неверно, javascript имеет асинхронные операторы true, но это происходит не потому, что функция занимает много времени, когда поток автоматически перескакивает дальше, что зависит от того, является ли это функцией async или нет. Btw Java может быть асинхронной в более поздних версиях, она намного реже. –
@NexusDuck - Большое вам спасибо! Это было то, чего мне не хватало. То есть (исправьте меня, если я ошибаюсь), JavaScript имеет эти встроенные функции, которые подвержены/или вызывают задержки, и они сделаны асинхронными, чтобы избежать проблем; что означает, что мы не можем настраивать собственные асинхронные функции (не полагаясь на что-то встроенное) Я прав? – Savvy
Вы правы, посмотрите на ответ @ jfriend00, у него более подробная версия (важно, что javascript имеет более асинхронный характер, потому что он однопоточный, а не Java, который может быть многопоточным) –