Чем сложнее логика вашей программы, тем сложнее разобраться с асинхронным кодом. async
и await
- два ключевых слова, которые могут помочь сделать асинхронный код более похожим на синхронный. В результате код будет выглядеть чище, сохраняя при этом преимущества асинхронного кода.
Например, два приведенных ниже блока кода идентичны: оба получают информацию с сервера, обрабатывают ее и возвращают promise.
function getPersonsInfo(name) {
return server.getPeople().then(people => {
return people.find(person => { return person.name === name });
});
}
async function getPersonsInfo(name) {
const people = await server.getPeople();
const person = people.find(person => { return person.name === name });
return person;
}
Второй пример выглядит проще и больше похож на стандартные функции, которые вы привыкли писать. Однако вы, наверняка, заметили ключевое слово async
? А как насчет ключевого слова await
перед server.getPeople()
?
- Как объявить
async
функцию? - Что делает ключевое слово
async
? - Что делает ключевое слово
await
? - Что возвращается из
async
функции? - Что происходит, когда внутри
async
функции происходит ошибка? - Как можно обработать ошибки внутри функции
async
?
Ключевое слово async
позволяет движку JavaScript понять, что вы объявляете асинхронную функцию. Данное ключевое слово обязательно при использовании await
внутри функции. Когда функция объявляется с помощью async
, она автоматически возвращает promise, возвращение значение из функции async
аналогично выполнению обещания (resolve
). Исключение же отклонению обещания (reject
).
Напомним: promise = обещание
Важно понимать, что async
функции являются просто синтаксическим сахаром для обещаний.
Ключевое слово async
без проблем может использоваться с любым из способов создания функции. Иначе говоря: можно использовать функцию async
везде, где вы можете использовать обычную функцию. Ниже представлены примеры, которые могут быть интуитивно не понятны. Сделайте задание и вернитесь к ним позже.
const yourAsyncFunction = async () => {
// делаем что-то асинхронное и возвращаем promise
return result;
}
anArray.forEach(async item => {
// делаем что-то асинхронное для каждого элемента массива 'anArray'
// можно также использовать .map, чтобы вернуть массив обещаний (promise) для 'Promise.all()'
});
server.getPeople().then(async people => {
people.forEach(person => {
// делаем что-то асинхронное для каждого человека
});
});
await
прост: данное ключевое слово сообщает JavaScript дождаться завершения асинхронного действия. Это как "сделаем паузу до готовности". Ключевое слово await
используется для получения значения из функции (обычно в таком случае вы используете .then()
). Вместо вызова .then()
после асинхронной функции вы просто присваиваете результат переменной с помощью await
. После вы можете использовать результат в своем коде, как в синхронном коде.
Обработка ошибок в функциях async
достаточно проста. Promise имеет метод .catch()
для обработки отклоненных обещаний. Поскольку асинхронные функции возвращают обещание, вы можете просто вызвать функцию и добавить метод .catch()
в конец.
asyncFunctionCall().catch(err => {
console.error(err)
});
Но есть и другой путь - великолепный блок try/catch
! Если вы хотите обработать ошибку непосредственно внутри функции async
, вы можете использовать try/catch
так же, как и внутри синхронного кода.
async function getPersonsInfo(name) {
try {
const people = await server.getPeople();
const person = people.find(person => { return person.name === name });
return person;
} catch (error) {
// Обработайте ошибку любым удобным способом
}
}
Может выглядеть достаточно грязно, но это простой способ обработки ошибок без .catch()
. То, как вы обрабатываете ошибки, зависит от вас и вашего кода. Вы почувствуете, что нужно сделать со временем и с опытом. Задания также помогут вам разобраться с обработкой ошибок.
Помните наш проект с API Giphy? (Нет? Вернитесь и закончите урок по API) Давайте изменим код, основанный на обещаниях, в async/await
код. Давайте начнем со следующего:
<script>
const img = document.querySelector('img');
fetch('https://api.giphy.com/v1/gifs/translate?api_key=ВАШ_КЛЮЧ&s=cats', {mode: 'cors'})
.then(function(response) {
return response.json();
})
.then(function(response) {
img.src = response.data.images.original.url;
});
</script>
Поскольку await
не работает в глобальной области видимости, нам нужно будет создать async
функцию, которая обернет наш вызов API Giphy.
<script>
const img = document.querySelector('img');
async function getCats() {
fetch('https://api.giphy.com/v1/gifs/translate?api_key=ВАШ_КЛЮЧ&s=cats', {mode: 'cors'})
.then(function(response) {
return response.json();
})
.then(function(response) {
img.src = response.data.images.original.url;
});
}
</script>
Теперь, когда у нас есть асинхронная функция, мы можем заменить promise
на await
.
<script>
const img = document.querySelector('img');
async function getCats() {
const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=ВАШ_КЛЮЧ&s=cats', {mode: 'cors'});
response.json().then(function(response) {
img.src = response.data.images.original.url;
});
}
</script>
Поскольку response
- это все тот же объект, который мы передавали ранее в блок .then()
, нам все равно нужно использовать метод .json()
. Метод .json()
в свою очередь, возвращает обещание. Следовательно мы можем использовать await
, чтобы присвоить переменной ответ.
<script>
const img = document.querySelector('img');
async function getCats() {
const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=ВАШ_КЛЮЧ&s=cats', {mode: 'cors'});
const catData = await response.json();
img.src = catData.data.images.original.url;
}
</script>
Чтобы использовать эту функцию, нам достаточно вызвать ее с помощью getCats()
.
<script>
const img = document.querySelector('img');
async function getCats() {
const response = await fetch('https://api.giphy.com/v1/gifs/translate?api_key=111111&s=cats', {mode: 'cors'});
const catData = await response.json();
img.src = catData.data.images.original.url;
}
getCats();
</script>
Код будет вести себя точно так же, как и код с прошлого урока, но выглядеть иначе. async/await
- очень полезный инструмент для упрощения асинхронного кода JavaScript. Важно помнить, что async/await
под капотом - просто обещания, написанные по-другому. Выполните задания, приведенные ниже, и углубитесь в понятие async/await
.
- Прочитайте эту статью, чтобы хорошенько ознакомиться с
async/await
. Данная статья и данная на русском на примерах раскрывает тему. - Прочитайте эту статью для более глубокого изучения
async/await
. Она включает раздел об обработке ошибок. - Посмотрите обзороне видео о
async/await
, его назначении и различных трюках трюка. Аналогичное видео на русском.
- Видео является примером того, как вы можете переработать ваш код с коллбеками, обещаниями на
async/await
.