JS Tower
JavaScript & TypeScriptМодуль 5: Асинхронность

Async/Await

Современный синтаксис для асинхронного кода

Цель урока

В этом уроке ты научишься:

  • Использовать async/await
  • Обрабатывать ошибки
  • Выполнять параллельные операции

Основы

async функция

async function getData() {
  return "Данные";
}

// Возвращает Promise
getData().then(result => console.log(result)); // "Данные"

await

Приостанавливает выполнение до разрешения промиса:

async function getData() {
  let result = await fetch("/api/data");
  let data = await result.json();
  return data;
}

Важно

await можно использовать только внутри async функции.


Сравнение с промисами

Промисы

function loadUser(id) {
  return fetch(`/api/users/${id}`)
    .then(response => response.json())
    .then(user => fetch(`/api/posts?userId=${user.id}`))
    .then(response => response.json())
    .then(posts => {
      console.log(posts);
    });
}

Async/await

async function loadUser(id) {
  let response = await fetch(`/api/users/${id}`);
  let user = await response.json();
  
  let postsResponse = await fetch(`/api/posts?userId=${user.id}`);
  let posts = await postsResponse.json();
  
  console.log(posts);
}

Обработка ошибок

try/catch

async function getData() {
  try {
    let response = await fetch("/api/data");
    let data = await response.json();
    return data;
  } catch (error) {
    console.log("Ошибка:", error.message);
    return null;
  }
}

finally

async function getData() {
  try {
    let data = await fetch("/api/data");
    return data;
  } catch (error) {
    console.log("Ошибка");
  } finally {
    console.log("Завершено");
  }
}

Параллельное выполнение

Последовательно (медленно)

async function loadData() {
  let users = await fetch("/api/users").then(r => r.json());
  let posts = await fetch("/api/posts").then(r => r.json());
  let comments = await fetch("/api/comments").then(r => r.json());
  
  return { users, posts, comments };
}
// Время: T1 + T2 + T3

Параллельно (быстро)

async function loadData() {
  let [users, posts, comments] = await Promise.all([
    fetch("/api/users").then(r => r.json()),
    fetch("/api/posts").then(r => r.json()),
    fetch("/api/comments").then(r => r.json())
  ]);
  
  return { users, posts, comments };
}
// Время: max(T1, T2, T3)

Стрелочные async функции

const getData = async () => {
  let result = await fetch("/api/data");
  return result.json();
};

// В методах
const obj = {
  async load() {
    return await fetch("/api/data");
  }
};

// В callback
const results = await Promise.all(
  urls.map(async url => {
    let response = await fetch(url);
    return response.json();
  })
);

Циклы с await

for...of

async function processItems(items) {
  for (let item of items) {
    await processItem(item);
  }
}

Параллельная обработка

async function processItems(items) {
  await Promise.all(
    items.map(item => processItem(item))
  );
}

Выбор подхода

Используй for...of для последовательной обработки, Promise.all для параллельной.


Top-level await

В модулях можно использовать await на верхнем уровне:

// module.js
let response = await fetch("/api/config");
export let config = await response.json();

Практические примеры

Повторные попытки

async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (error) {
      if (i === retries - 1) throw error;
      await delay(1000 * (i + 1));
    }
  }
}

Таймаут

async function fetchWithTimeout(url, timeout = 5000) {
  let controller = new AbortController();
  let timeoutId = setTimeout(() => controller.abort(), timeout);
  
  try {
    let response = await fetch(url, { signal: controller.signal });
    return response;
  } finally {
    clearTimeout(timeoutId);
  }
}

Практика

Задание 1: Базовый async/await

Задача: Создай async функцию с задержкой.

Loading...
Ваш вывод:

Задание 2: Обработка ошибок

Задача: Обработай ошибку с помощью try/catch.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
Ошибка: Что-то пошло не так
Завершено

Задание 3: Параллельное выполнение

Задача: Выполни 3 операции параллельно.

Запустите код для проверки
Loading...
Ваш вывод:
Ожидаемый результат:
[1,2,3]

Проверь себя

  1. Что возвращает async функция?
  2. Как обработать ошибку в async/await?
  3. Как выполнить операции параллельно?