Что должно быть в правой части после await?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разбор оператора await в JavaScript
await — это ключевое слово, которое используется внутри асинхронных функций (async function) для приостановки выполнения функции до тех пор, пока Promise (обещание) не будет выполнено (fulfilled) или отклонено (rejected). После await в правой части может находиться несколько типов значений, но их поведение всегда сводится к работе с Promise.
Что может находиться после await?
1. Promise (обещание)
Это наиболее частый и прямолинейный случай. await "ждёт" разрешения (settlement) Promise: если Promise выполняется успешно (fulfilled), await возвращает его результат (value); если отклоняется (rejected), генерируется исключение.
async function fetchData() {
// Ожидание разрешения Promise, возвращаемого fetch
const response = await fetch('https://api.example.com/data');
const data = await response.json(); // response.json() также возвращает Promise
return data;
}
2. Thenable объект (объект с методом .then())
await работает не только с нативными Promise, но и с любым объектом, имеющим метод .then() (соответствующий спецификации Promise/A+). Это позволяет использовать await со сторонними библиотеками, реализующими свои аналоги Promise.
// Пример с jQuery Deferred (thenable объект)
async function waitForJQuery() {
const deferred = $.Deferred();
setTimeout(() => deferred.resolve('Done!'), 1000);
const result = await deferred; // await работает, так как deferred имеет .then()
console.log(result); // 'Done!'
}
3. Любое не-Promise значение
Если после await стоит значение, которое не является Promise или thenable объектом, JavaScript автоматически оборачивает его в уже выполненный Promise (Promise.resolve(value)). Это позволяет использовать await единообразно, даже если функция может возвращать как асинхронные, так и синхронные значения.
async function example() {
const num = await 42; // Не Promise, будет обёрнут в Promise.resolve(42)
const str = await 'Hello'; // Аналогично
const bool = await true; // И так далее
console.log(num, str, bool); // 42, 'Hello', true
return 'All done';
}
// Это эквивалентно:
async function equivalent() {
const num = await Promise.resolve(42);
// ...
}
4. Вызов асинхронной функции (async function)
Асинхронные функции всегда возвращают Promise. Поэтому вызов такой функции после await — это частный случай работы с Promise.
async function innerAsync() {
return 'Result from inner';
}
async function outerAsync() {
const result = await innerAsync(); // Ожидание Promise, возвращённого innerAsync
console.log(result); // 'Result from inner'
}
5. Вызов синхронной функции, возвращающей Promise
Это самый распространённый сценарий на практике: функции, возвращающие Promise (например, fetch, fs.promises.readFile в Node.js, setTimeout с обёрткой и т.д.).
async function readFile() {
const fs = require('fs').promises;
const content = await fs.readFile('file.txt', 'utf-8'); // fs.readFile возвращает Promise
console.log(content);
}
Ключевые особенности поведения await
- Приостановка и возобновление:
awaitприостанавливает выполнение текущей асинхронной функции, но не блокирует основной поток JavaScript. Другие операции (обработка событий, таймеры, другие асинхронные задачи) могут выполняться. - Обработка ошибок: Если Promise после
awaitотклоняется (rejects), генерируется исключение. Его необходимо перехватывать с помощьюtry/catch.
async function riskyOperation() {
try {
const data = await fetch('https://invalid-url');
} catch (error) {
console.error('Fetch failed:', error); // Перехват ошибки сети или отклонённого Promise
}
}
- Преобразование синхронных ошибок: Если после
awaitвозникает синхронная ошибка (например, в выражении), она также преобразуется в отклонённый Promise.
async function willThrow() {
const value = await (() => { throw new Error('Sync error!'); })();
// Синхронная ошибка будет "обёрнута" в отклонённый Promise
}
Важные нюансы
awaitработает только внутриasyncфункций (кроме top-level await в модулях ES2022+).- Не используйте
awaitбез необходимости для не-Promise значений, так как это добавляет микротаску в очередь событий и может неоптимально сказаться на производительности. - Параллельное выполнение: Для параллельного ожидания нескольких Promise используйте
Promise.all().
async function parallel() {
// НЕПРАВИЛЬНО (последовательное выполнение)
// const a = await fetchA();
// const b = await fetchB(); // Начнётся только после fetchA
// ПРАВИЛЬНО (параллельное выполнение)
const [a, b] = await Promise.all([fetchA(), fetchB()]);
}
Таким образом, после await может находиться любое выражение. Механизм всегда стремится преобразовать результат этого выражения к Promise, а затем дождаться его разрешения, что делает асинхронный код более линейным и читаемым, похожим на синхронный.