Синхронная операция блокирует процесс до завершения операции. Асинхронная операция неблокирующая и только инициирует операцию. Завершение можно обнаружить и другими способами.
Чтобы понять, как работает асинхронизм в Javascript, давайте сначала поговорим о том, как promises раскрывает этот метод завершения.
Представлено в ES (2015 г.)
Обещание, которое вы говорите?
В точности то, что он означает, простыми словами, объект Promise
представляет окончательное завершение (или отказ) асинхронной операции и ее результирующее значение.
var promise1 = new Promise(function(resolve, reject) { setTimeout(function() { resolve('foo'); }, 300); }); promise1.then(function(value) { console.log(value); // expected output: "foo" }); console.log(promise1); // expected output: [object Promise]
Более подробно объяснено в документации
Promise
- это прокси для значения, не обязательно известного на момент создания обещания. Он позволяет связать обработчики с конечным значением успеха или причиной сбоя асинхронного действия. Это позволяет асинхронным методам возвращать значения, как синхронные методы: вместо того, чтобы немедленно возвращать окончательное значение, асинхронный метод возвращает обещание предоставить значение в какой-то момент в будущем.
Promise
находится в одном из следующих состояний:
- ожидает: начальное состояние, ни выполнено, ни отклонено.
- выполнено: означает, что операция успешно завершена.
- отклонено: это означает, что операция не удалась.
Отложенное обещание может быть выполнено со значением или отклонено с указанием причины (ошибка). Когда происходит любой из этих вариантов, вызываются связанные обработчики, поставленные в очередь then
method обещания. (Если обещание уже выполнено или отклонено при присоединении соответствующего обработчика, обработчик будет вызван, поэтому между завершением асинхронной операции и присоединением ее обработчиков не возникает состояния гонки.)
Поскольку методы Promise.prototype.then()
и Promise.prototype.catch()
возвращают обещания, их можно объединить в цепочку.
Асинхронный / Ожидание
Представленное в ES2017 объявление функции Async/Await
определяет асинхронную функцию, которая возвращает объект AsyncFunction. Асинхронная функция - это функция, которая работает асинхронно через цикл событий, используя неявное обещание для возврата своего результата.
Но синтаксис и структура вашего кода с использованием асинхронных функций намного больше похожи на использование стандартных синхронных функций.
function resolveAfter2Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 2000); }); } async function asyncCall() { console.log('calling'); var result = await resolveAfter2Seconds(); console.log(result); // expected output: 'resolved' } asyncCall();
Более подробно объяснено в документации
Функция async
может содержать выражение await
, которое приостанавливает выполнение асинхронной функции и ожидает переданного разрешения Promise
, а затем возобновляет выполнение async
функции и возвращает разрешенное значение.
Помните, что ключевое слово await
допустимо только внутри async
функций. Если вы используете его вне тела async
функции, вы получите SyntaxError
.
Попробуй поймать
Оператор try...catch
отмечает блок операторов для попытки и указывает ответ на случай возникновения исключения.
function getProcessedData(url) {
return downloadData(url) // returns a promise
.catch(e => {
return downloadFallbackData(url) // returns a promise
})
.then(v => {
return processDataInWorker(v); // returns a promise
});
}
Это можно переписать как
async function getProcessedData(url) {
let v;
try {
v = await downloadData(url);
} catch(e) {
v = await downloadFallbackData(url);
}
return processDataInWorker(v);
}
Сноска: ES (2019) представила необязательную привязку catch, которая позволяет просто опускать переменную, включая круглые скобки после
catch
Более подробно объяснено в документации
Оператор try
состоит из блока try
, который содержит один или несколько операторов. {}
следует использовать всегда, даже для отдельных операторов. Должно присутствовать хотя бы одно предложение catch
или предложение finally
. Это дает нам три формы для оператора try
:
try...catch
try...finally
try...catch...finally
Предложение catch
содержит инструкции, которые определяют, что делать, если в блоке try
возникает исключение. То есть вы хотите, чтобы блок try
успешно завершился, и если он не удастся, вы хотите передать управление блоку catch
. Если какой-либо оператор в блоке try
(или в функции, вызываемой из блока try
) вызывает исключение, управление немедленно переходит к предложению catch
. Если в блоке try
не возникает исключения, предложение catch
пропускается.
Предложение finally
выполняется после блока try
и предложений catch
, но до операторов, следующих за оператором try
. Он выполняется всегда, независимо от того, было выбрано исключение.
Вы можете вложить один или несколько операторов try
. Если внутренний оператор try
не имеет предложения catch
, вводится предложение catch
включающего оператора try
.
В заключение
Обработка асинхронного кода иногда может быть проблемой, но если вы действительно хотите овладеть этим важным навыком, практика и понимание этих ключевых концепций помогут вам в этом.