Skip to content

Latest commit

 

History

History
185 lines (142 loc) · 11.2 KB

00151.md

File metadata and controls

185 lines (142 loc) · 11.2 KB

Async и Await

Введение

Чем сложнее логика вашей программы, тем сложнее разобраться с асинхронным кодом. 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()?

По окончанию

  1. Как объявить async функцию?
  2. Что делает ключевое слово async?
  3. Что делает ключевое слово await?
  4. Что возвращается из async функции?
  5. Что происходит, когда внутри async функции происходит ошибка?
  6. Как можно обработать ошибки внутри функции 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

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.

  1. Прочитайте эту статью, чтобы хорошенько ознакомиться с async/await. Данная статья и данная на русском на примерах раскрывает тему.
  2. Прочитайте эту статью для более глубокого изучения async/await. Она включает раздел об обработке ошибок.
  3. Посмотрите обзороне видео о async/await, его назначении и различных трюках трюка. Аналогичное видео на русском.

Дополнительные ресурсы

  1. Видео является примером того, как вы можете переработать ваш код с коллбеками, обещаниями на async/await.