Введение
В современном JavaScript есть такие возможности, как Promises, стрелочные функции и т.д. Ни одна из них, на мой взгляд, не является большим улучшением языка, чем Async-Await. Async-Await упрощает работу с нашим кодом на основе обещаний, который выглядит скорее синхронным, чем асинхронным.
В этой статье мы подробно рассмотрим, как работают функции Async, их преимущества и практические примеры использования.
Что такое Async-Await?
Async Await — это просто небольшой набор инструментов, облегчающих работу с обещаниями. Он позволяет непрерывно использовать методы обещаний и помогает нам лучше управлять множеством асинхронных действий при создании наших приложений.
Предварительные условия
-
Как пользоваться командной строкой/терминалом.
-
Базовое понимание обещаний Javascript.
-
Написание стрелочных функций.
-
Использование setTimeout().
-
Установлен Node.
Начало работы
Мы начнем с создания каталога, содержащего наш файл JavaScript. Вы можете перейти в терминал и набрать следующее:
mkdir async
Чтобы изменить каталог на async
, введите следующий код:
cd async
Чтобы создать новый файл Javascript под названием «async-await.js» с переменной внутри, введите код ниже:
echo var msg > async-await.js
Теперь мы можем открыть нашу директорию в visual studio code с помощью команды ниже:
code .
Функции и Async-функции (чем они отличаются)
Чтобы действительно понять, чем функции отличаются от Async-функций, давайте создадим стрелочную функцию под названием ‘doWork’. Эта функция будет пустой, и мы будем записывать ее результат в консоль, используя приведенный ниже код:
let doWork = () => {
};
console.log(doWork())
При запуске нашего файла async-await.js на терминале будет выведено неопределенное значение, потому что функции обычно ожидают возврата значения. Чтобы запустить наш файл, откройте командную строку и введите:
node async-await
Чтобы сделать нашу функцию асинхронной, достаточно пометить ее как асинхронную непосредственно перед объявлением функции. т.е.
let doWork = async () => {
};
console.log(doWork())
Этим небольшим изменением кода мы уже меняем поведение нашей программы. Мы больше не будем видеть неопределенную печать в терминале. Чтобы убедиться в этом, нам нужно запустить наш файл еще раз, используя:
node async-await
В этом случае мы получим обещание, которое было выполнено со значением undefined.
Это первое, что нужно отметить об асинхронных функциях: асинхронные функции всегда возвращают обещание. Это обещание выполняется со значением, которое вы решили вернуть из функции. В настоящее время мы ничего не возвращаем, поэтому обещание выполняется с неопределенным значением.
Теперь давайте явно вернем значение из функции async. Для этого вернем строку, содержащую мое имя.
let doWork = async () => {
return "Emmanuel"
};
console.log(doWork())
Следует отметить, что возвращаемое значение из doWork()
— это не «Эммануил», это все еще Promise, которое было выполнено со строкой «Эммануил». Когда мы запускаем наш код, мы видим, что это значит.
Использование .then()
и .catch()
Мы не делаем многого, просто регистрируя возвращаемое значение, давайте посмотрим, как использовать метод .then() для запуска некоторого кода при выполнении функции async.
Для этого нам просто нужно использовать метод .then() в нашей функции doWork. В качестве примера, мы просто занесем в журнал результат ее встроенной функции arrow. Которая содержит возвращаемое значение асинхронной функции
let doWork = async () => {
return "Emmanuel"
};
doWork().then((result) => {
console.log("Result", result)
})
Вот result
для этого:
Мы также можем настроить вызов .catch(), который представляет собой просто функцию, получающую ошибку. Давайте подключим его к нашему методу .then() с помощью приведенного ниже кода:
let doWork = async () => {
return "Emmanuel"
};
doWork().then((result) => {
console.log("Result", result)
}).catch((e) => {
console.log("e", e);
})
Только одна небольшая проблема, когда мы запускаем наш файл, мы все еще получаем результат «Emmanuel».
Итак, как же нам заставить .catch() работать?
Если мы выбросим ошибку из нашей асинхронной функции, это будет то же самое, что отклонить обещание, отправленное обратно из асинхронной функции.
Чтобы выбросить ошибку, измените свой код на приведенный ниже:
let doWork = async () => {
throw New Error("Something went wrong")
return "Emmanuel"
};
doWork().then((result) => {
console.log("Result", result)
}).catch((e) => {
console.log("e", e);
})
На этот раз при выполнении нашего кода мы получим строку «e», а также весь объект ошибки.
Использование оператора Await
До сих пор мы рассматривали базовую структуру асинхронных функций. Теперь нам предстоит изучить вторую половину асинхронных функций —Await функцию.
Оператор await
можно использовать только в асинхронных функциях, а поскольку вся суть асинхронного await заключается в том, чтобы упростить работу с кодом, основанным на обещаниях.
Чтобы оживить ситуацию, давайте создадим код на основе обещания, это будет просто обещание, которое складывает два числа через две секунды, вот код для этого:
const add = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b)
}, 2000)
})
}
let doWork = async () => {
throw New Error("Something went wrong")
return "Emmanuel"
};
doWork().then((result) => {
console.log("Result", result)
}).catch((e) => {
console.log("e", e);
})
Если бы мы использовали цепочку обещаний, код потребовал бы вызовов .then() и функций обратного вызова, просто чтобы получить значение add().
Async-Await устраняет этот монотонный способ выполнения задач.
То, к чему мы получаем доступ внутри нашей async-функции, — это оператор await. Оператор await работает с обещаниями. И поскольку у нас уже есть обещание под названием add
, мы будем использовать его с оператором await. Мы собираемся сложить два числа вместе, а затем ожидать результата обещания add, который мы сохраним в нашей переменной под названием «sum», а затем вернем значение «sum».
const add = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b)
}, 2000)
})
}
let doWork = async () => {
const sum = await add(1, 99);
return sum
};
doWork().then((result) => {
console.log("Result", result)
}).catch((e) => {
console.log("e", e);
})
Когда мы снова запустим наш файл async-await.js
, мы получим результат, показанный ниже.
Выполнение нескольких задач с помощью Async-Await
Замечательно, мы впервые использовали await в нашем приложении. Мы можем пойти еще дальше, выполняя другие задачи на основе обещаний в нашей функции async.
Я буду делать больше вызовов add(), используя значение предыдущих сумм. Вот код для этого
const doWork = async () => {
const sum = await add(1, 99)
const sum2 = await add(sum, 50)
const sum3 = await add(sum2, 3)
return sum3
}
Это сделает несколько обращений к sum, и нам придется ждать 2 секунды, пока каждое обещание будет выполнено. Это говорит нам о том, что async-await не обязательно делает все быстрее, он просто упрощает работу. После 6 секунд ожидания мы получим конечный результат 153
Одно из преимуществ, которое дает нам Async-Await, — это возможность поместить все вызовы обещаний в одну область видимости. Это делает код более читабельным и синхронным.
Теперь осталось завершить работу, написав код обработки ошибок, когда наши обещания будут отклонены. Мы добавим оператор if, который поможет нам проверить, являются ли числа, складываемые функцией sum(), отрицательными. Мы вернем код отклонения, чтобы он завершил работу и отклонил обещание, если это условие выполнено.
Давайте улучшим нашу функцию add(), добавив оператор if.
const add = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (a < 0 || b < 0) {
return reject('Numbers must be non-negative')
}
resolve(a + b)
}, 2000)
})
}
Если мы запустим наш файл async-await
после добавления этого оператора, мы получим тот же результат, но когда мы внесем некоторые изменения в числа в add(), мы получим ошибку: Вот код и изображение для этого ниже:
const add = (a, b) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (a < 0 || b < 0) {
return reject('Numbers must be non-negative')
}
resolve(a + b)
}, 2000)
})
}
const doWork = async () => {
const sum = await add(1, -99)
const sum2 = await add(sum, 50)
const sum3 = await add(sum2, -3)
return sum3
}
doWork().then((result) => {
console.log('result', result)
}).catch((e) => {
console.log('e', e)
})
Выход:
Вывод будет зарегистрирован после того, как мы подождем начальные 2 секунды, которые указаны в нашей функции setTimeout().
Заключение
Итак, мы рассмотрели, чем async await отличается от функций, оператор await и как выполнять несколько задач с помощью async-await. Мы также узнали, что async-await дает нам одну область для размещения наших обещаний.
Я надеюсь, что эта статья была полезной, пожалуйста, оставьте комментарий и следите за мной, чтобы получать больше материалов.