Async/Await

13-07-24 16:43:49


Image for the Async/Await

Почему Async/Await?

До введения async/await разработчики в основном использовали коллбеки и промисы для обработки асинхронных операций. Хотя промисы улучшили читаемость и управление асинхронным кодом по сравнению с коллбеками, цепочка нескольких промисов все же приводила к сложному и менее читаемому коду. Async/await упрощает это, позволяя разработчикам писать асинхронный код, который выглядит и ведет себя как синхронный код.

Преимущества Async/Await:

  • Читаемость: Async/await предоставляет синтаксис, который намного ближе к синхронному коду, улучшая читаемость.
  • Обработка ошибок: Использование try/catch с async/await делает обработку ошибок более простой и последовательной.
  • Поддерживаемость: Async/await приводит к более чистому и поддерживаемому коду.
  • Отладка: Отладка кода с async/await часто проще по сравнению с цепочками промисов, так как трассировки стека более информативны.

Основы Async/Await

Ключевое слово async используется для объявления асинхронной функции, которая неявно возвращает промис. Ключевое слово await используется для приостановки выполнения асинхронной функции до тех пор, пока промис не будет разрешен, возвращая разрешенное значение.

async function exampleFunction() {
// Код здесь
}

await examplePromise;

Преобразование Функции на Основе Промисов в Async/Await

Рассмотрим следующую функцию на основе промисов:

function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = { user: 'John Doe' };
resolve(data);
}, 1000);
});
}

// Использование функции на основе промисов
fetchData().then(data => {
console.log(data); // Вывод: { user: 'John Doe' }
}).catch(error => {
console.error(error);
});

Мы можем преобразовать эту функцию, чтобы использовать async/await следующим образом:

async function fetchDataAsync() {
try {
const data = await fetchData();
console.log(data); // Вывод: { user: 'John Doe' }
} catch (error) {
console.error(error);
}
}

// Вызов асинхронной функции
fetchDataAsync();

Обработка Ошибок с Async/Await

Обработка ошибок в async/await выполняется с помощью блоков try/catch, что предоставляет более интуитивный и последовательный подход по сравнению с цепочками промисов.

async function fetchDataWithError() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('Ошибка при получении данных');
}, 1000);
});
}

async function fetchDataAsyncWithErrorHandling() {
try {
const data = await fetchDataWithError();
console.log(data);
} catch (error) {
console.error('Пойманная ошибка:', error); // Вывод: Пойманная ошибка: Ошибка при получении данных
}
}

// Вызов асинхронной функции с обработкой ошибок
fetchDataAsyncWithErrorHandling();

Последовательное и Параллельное Выполнение

Async/await позволяет как последовательное, так и параллельное выполнение асинхронных операций, в зависимости от того, как используется ключевое слово await.

Последовательное Выполнение:

В последовательном выполнении каждая операция ждет завершения предыдущей перед началом следующей.

async function sequentialExecution() {
const data1 = await fetchData();
console.log(data1);

const data2 = await fetchData();
console.log(data2);
}

sequentialExecution();

Параллельное Выполнение:

В параллельном выполнении несколько операций запускаются одновременно, и мы ждем их завершения вместе.

async function parallelExecution() {
const promise1 = fetchData();
const promise2 = fetchData();

const [data1, data2] = await Promise.all([promise1, promise2]);
console.log(data1, data2);
}

parallelExecution();

Использование Async/Await с Fetch API

Fetch API часто используется для выполнения сетевых запросов, и он прекрасно работает с async/await.

async function fetchUserData(userId) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error('Проблема с сетью');
}
const userData = await response.json();
console.log(userData);
} catch (error) {
console.error('Ошибка Fetch:', error);
}
}

fetchUserData(1);