Внедение стандарта ES2017 в JavaScript привнесло два новых оператора: async и await, который призваны упростить работу с промисами.
Оператор async определяет асинхронную функцию, в которой, как предполагается, будет выполняться одна или несколько асинхронных задач:
async function название_функции(){ // асинхронные операции }
Внутри асинхронной функции мы можем применить оператор await. Он ставится перед вызовом асинхронной операции, которая представляет объект Promise:
async function название_функции(){ await асинхронная_операция(); }
Оператор await приостанавливает выполнение асинхронной функции, пока асинхронная операция (объект Promise) не возвратит результат.
Стоит учитывать, что оператор await может использоваться только внутри функции, к которой применяется оператор async.
Сначала рассмотрим самый простейший пример с использованием Promise:
function sum(x, y){ return new Promise(function(resolve){ const result = x + y; resolve(result); }); } sum(5, 3).then(function(value){ console.log("Результат асинхронной операции:", value); }); // Результат асинхронной операции: 8
В данной случае функция sum()
представляет асинхронную задачу. Она принимает два числа и возвращает объект Promise, в котором выполняется сложение этих чисел. Результат сложения передается в функцию resolve()
. И далее
в методе then()
мы можем получить этот результат и выполнить с ним различные действия.
Теперь перепишем этот пример с использованием async/await:
function sum(x, y){ return new Promise(function(resolve){ const result = x + y; resolve(result); }); } // сокращенный вариант // function sum(x, y){ return Promise.resolve(x + y);} async function calculate(){ const value = await sum(5, 3); console.log("Результат асинхронной операции:", value); } calculate(); // Результат асинхронной операции: 8
Здесь мы определили асинхронную функцию calculate()
, к которой применяется async:
async function calculate(){
Внутри функции вызывается асинхронная операция sum()
, которой передаются некоторые значения.
Причем к этой функции применяется оператор await. Благодаря оператору await
больше нет надобности вызывать у промиса метод
then(). А результат, который возвращает Promise, мы можем получить напрямую из вызова функции sum и, например, присвоить константе или переменной:
const value = await sum(5, 3);
Затем мы можем вызвать функцию calculate()
как обычную функции и тем самым выполнить все ее действия.
calculate();
Поскольку т
Стоит отметить, что для функции, которая определена со словом async неявно создается объект Promise. Поэтому ее также можно использовать как промис:
function sum(x, y){ return new Promise(function(resolve){ const result = x + y; resolve(result); }); } async function calculate(){ const result = await sum(5, 3); return result; } calculate().then(value=> console.log("Результат асинхронной операции:", value));
Асинхронная функция может содержать множество асинхронных операций, к которым применяется оператор await. В этом случае все асинхронные операции будут выполняться последовательно:
function sum(x, y){ return new Promise(function(resolve){ const result = x + y; resolve(result); }); } async function calculate(){ const value1 = await sum(5, 3); console.log("Результат 1 асинхронной операции:", value1); const value2 = await sum(6, 4); console.log("Результат 2 асинхронной операции:", value2); const value3 = await sum(7, 5); console.log("Результат 3 асинхронной операции:", value3); } calculate(); // Результат 1 асинхронной операции: 8 // Результат 2 асинхронной операции: 10 // Результат 3 асинхронной операции: 12
Для обработки ошибок, которые могут возникнуть в процессе вызова асинхронной операции применяется конструкция try..catch..finally.
Например, возьмем следующий код с использованием Promise:
function square(str){ return new Promise((resolve, reject) => { const n = parseInt(str); if (isNaN(n)) reject("Not a number"); else resolve(n * n); }); }; function calculate(str){ square(str) .then(value => console.log("Result: ", value)) .catch(error => console.log(error)); } calculate("g8"); // Not a number calculate("4"); // Result: 16
Функция square()
получает некоторое значение, в промисе это значение преобразуется в число. И при удачном преобразовании из промиса
возвращается квадра числа. Если переданное значение не является числом, то возвращаем ошибку.
При вызове функции square()
с помощью метода catch() можно обработать возникшую ошибку.
Теперь перепишем пример с использованием async/await:
function square(str){ return new Promise((resolve, reject) => { const n = parseInt(str); if (isNaN(n)) reject("Not a number"); else resolve(n * n); }) }; async function calculate(str){ try{ const value = await square(str); console.log("Result: ", value); } catch(error){ console.log(error); } } calculate("g8"); // Not a number calculate("4"); // Result: 16
Вызов асинхронной операции помещается в блок try, соответственно в блоке catch можно получить возникшую ошибку и обработать ее.