Асинхронные коды — это в основном коды, которые не завершают свое выполнение в соответствии с обычным потоком блоков кода в сценарии. Другими словами, блоки кода, следующие за асинхронным кодом, могут завершить свое выполнение раньше асинхронного кода.

Итак, что особенного в асинхронных кодах?

Ниже приведен пример обычного скрипта (без асинхронных кодов):

console.log(“script start”); // prints to the console first
let data = [];
function sum(a, b) {
c = a + b;
data.push(c);
console.log(data);
}
sum(1, 2); // prints to the console second
console.log(“script done”); // prints to the console in third place

Как видите, коды в приведенном выше скрипте выполняются в соответствии с тем, как они вызываются. Но если у нас есть асинхронный код, такой как XMLHttpRequest() ниже, блоки кода в скрипте не будут выполняться в том порядке, в котором они вызываются.

См. ниже:

console.log(“script start”); // first execution: this prints to the console
function fetchData(url) {
const xmlhr = new XMLHttpRequest();
xmlhr.open(“GET”, url);
xmlhr.send();
xmlhr.onload = function () {
if (xmlhr.status === 200) {
console.log(xmlhr.responseText);
} else {
console.log(xmlhr.status);
}
};
return xmlhr.onload;
}
const url = prompt(“Enter URL”); // second execution: this prompts an input
fetchData(url); // fourth execution: this returns the result of xhr.onload
console.log(“script done”); // third execution: this prints to the console

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

Если коду требуется значение из асинхронного кода в вашем скрипте, код может:

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

· Выдать ошибку.

Чтобы избежать ситуации, когда код выдает ошибку, поскольку он зависит от асинхронного кода, в асинхронные коды добавляются обратные вызовы.

Обратные вызовы

Обратные вызовы — это функции, используемые в качестве аргументов в другой функции. Они предлагают некоторый контроль над последовательностью, в которой выполняются коды в скрипте.

Добавляя код в качестве обратного вызова к асинхронной функции (асинхронному коду), вы гарантируете, что такой код будет выполняться только тогда, когда асинхронная функция завершит свое выполнение. Таким образом, код будет инициирован только тогда, когда он получит значение из асинхронной функции. Следовательно, он не выдаст ошибку.

Если мы включим обратные вызовы в асинхронный скрипт выше, мы получим следующее:

console.log(“script start”); // first execution: this prints to the console
function fetchData(url, success, errorMessage) {
const xmlhr = new XMLHttpRequest();
xmlhr.open(“GET”, url);
xmlhr.send();
xmlhr.onload = function () {
if (xmlhr.status === 200) {
success(xmlhr.responseText);
} else {
errorMessage(xmlhr.status);
}
};
}
//success and errorMessage are callbacks. Either of them will execute, depending on the result of the fetchData() function called after them. They will not throw an error because they will surely wait for the asynchronous function — fetchData().
function success(output) {
console.log(output);
}
function errorMessage(status) {
console.log(`Error ${status}!`);
}
const url = prompt(“Enter URL”); // second excution: this prompts an input
fetchData(url, success, errorMessage);
console.log(“script done”); // third execution: this prints to the console

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

Краткое содержание

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

Если выполнение кода, вызванного после асинхронного кода, зависит от значения, возвращаемого асинхронным кодом, может возникнуть ошибка. Чтобы этого избежать, такие коды добавляются в асинхронные функции (асинхронные коды) в качестве обратных вызовов.