Вопрос проверяет понимание способов управления порядком выполнения асинхронных операций в JavaScript, что критично для задач, зависящих от предыдущих результатов.
В JavaScript операции, такие как сетевые запросы, чтение файлов или запросы к базам данных, часто выполняются асинхронно. Это означает, что они не блокируют основной поток, но их завершение может произойти в произвольном порядке. Однако многие сценарии требуют строгой последовательности: например, сначала нужно получить данные пользователя, затем его заказы, а потом отправить уведомление. Для управления этим порядком используются определённые паттерны.
Промисы (Promise) представляют будущий результат асинхронной операции. Метод .then() возвращает новый промис, что позволяет связывать вызовы. Каждый следующий .then выполнится только после разрешения промиса из предыдущего шага. Ошибки можно обрабатывать с помощью .catch() в конце цепочки.
function fetchUser(id) {
return fetch(`/api/users/${id}`).then(res => res.json());
}
fetchUser(1)
.then(user => {
console.log('User:', user);
return fetch(`/api/orders?userId=${user.id}`); // Возвращаем новый промис
})
.then(response => response.json())
.then(orders => {
console.log('Orders:', orders);
// Следующая операция...
})
.catch(error => {
console.error('Error in sequence:', error);
});Ключевые слова async и await предоставляют более декларативный способ работы с асинхронным кодом. Функция, объявленная как async, всегда возвращает промис. Внутри неё await приостанавливает выполнение до разрешения промиса, делая поток выполнения последовательным и понятным.
async function processUserData(userId) {
try {
const user = await fetch(`/api/users/${userId}`).then(res => res.json());
console.log('User:', user);
const ordersResponse = await fetch(`/api/orders?userId=${user.id}`);
const orders = await ordersResponse.json();
console.log('Orders:', orders);
// Далее можно выполнить другие операции последовательно
return orders;
} catch (error) {
console.error('Failed to process data:', error);
}
}
processUserData(1);Этот подход широко применяется при работе с API, обработке данных поэтапно или в любых сценариях, где результат одной операции является входными данными для следующей. Он делает код менее подверженным ошибкам, связанным с состоянием гонки (race conditions).
Вывод: Используйте async/await для нового кода, так как это улучшает читаемость и упрощает обработку ошибок через try/catch. Цепочка промисов остаётся фундаментальным паттерном и полезна, например, при динамической композиции операций.