Кратко
Async generator — async function* — функция, которая может приостанавливаться (yield) и выполнять асинхронные операции. for await...of перебирает асинхронные итераторы. Используется для: построчного чтения файлов, обработки стримов, постраничной загрузки данных.
Подробно
Async generator:
async function* fetchPages(url) {
let page = 1;
while (true) {
const response = await fetch(${url}?page=${page});
const data = await response.json();
if (data.length === 0) break;
yield data;
page++;
}
}
// Перебор: for await (const pageData of fetchPages('/api/users')) { console.log(pageData); }
Где используется:
- Построчное чтение файлов (Node.js)
- Постраничная загрузка
- WebSocket-like стримы
- Обработка данных по мере поступления
Синтаксис: async function* name() { yield await promise; }
// Или стрелочная (ограниченно) const gen = async function*() { yield 1; };
Ментальная модель
Async generator — как автомат с напитками с кнопкой «подождать». Вы нажимаете кнопку (next()) — автомат готовит напиток (await) — выдаёт его (yield). while(true) — автомат работает бесконечно, пока не закончатся напитки.
Примеры
**Самый простой:**
async function* numbers() {
yield 1;
yield new Promise(resolve => setTimeout(() => resolve(2), 100));
yield 3;
}
for await (const n of numbers()) {
console.log(n); // 1, 2 (через 100мс), 3
}Простейший async generator: yield с Promise.
**Простой:**
async function* fetchAll(urls) {
for (const url of urls) {
const response = await fetch(url);
const data = await response.json();
yield { url, data };
}
}
const urls = ['/api/users', '/api/posts'];
for await (const { url, data } of fetchAll(urls)) {
console.log(`${url}: ${data.length} items`);
}Последовательная загрузка данных с yield.
**Реальный пример:**
// Постраничная загрузка
async function* paginate(url, pageSize = 10) {
let offset = 0;
while (true) {
const response = await fetch(
`${url}?offset=${offset}&limit=${pageSize}`
);
const items = await response.json();
if (items.length === 0) return;
yield* items;
offset += pageSize;
}
}
// Загружаем все страницы
for await (const user of paginate('/api/users')) {
console.log(user.name);
}Постраничная загрузка: yield* для разворачивания массива.
Частые ошибки
**Неправильно:** Забывать await перед fetch в async generator
**Почему:** yield не ждёт Promise автоматически — нужен await.
**Правильно:** yield await promise; — правильный синтаксис.
**Неправильно:** Путать for...of и for await...of
**Почему:** for...of — для синхронных итераторов. for await...of — для асинхронных.
**Правильно:** async generator → for await...of. Обычный generator → for...of.
Важно запомнить
- async function* создаёт асинхронный генератор
- yield возвращает Promise
- for await...of перебирает асинхронные итераторы
- Используйте для: стримов, пагинации, построчного чтения
- return в async generator завершает итерацию
Связь
Назад: Вы знаете async/await (JA5) и генераторы (JV8). Асинхронные генераторы объединяют оба понятия.
Вперёд: Следующий урок (JV10) — промисификация — преобразование колбэков в Promise.