Полный цикл в digital

Асинхронные генераторы

Асинхронные итераторы открывают нам путь к созданию асинхронных генераторов. Асинхронные генераторы позволяют нам использовать оператор await и получать и возвращать данные асинхронным образом.

Для определения асинхронного генератора перед функцией генератора ставится оператор async:

async function* название_функции_генератора(){
yield возвращаемое_значение;
}

Рассмотрим простейший генератор:

async function* generatePersonAsync(){
yield "Tom";    
}

Здесь определен асинхронный генератор generatePersonAsync, в котором возвращается одно значение - строка Tom.

Особенностью асинхронного генератора является то, что при обращении к его методу next() возвращается объект Promise. А полученный объект Promise, в свою очередь возвращает объект с двумя свойствами { value, done }, где value собственно хранит возвращаемое значение, а done указывает доступны ли в генераторе еще данные.

Например, возьмем выше определенный асинхронный генератор:

async function* generatePersonAsync(){
yield "Tom";    
}
const personGenerator = generatePersonAsync();
personGenerator.next();  // Promise

Здесь с помощью метода next() получаем промис. Далее через метод then() мы можем получить из промиса объект:

const personGenerator = generatePersonAsync();
personGenerator.next()
.then(data => console.log(data));  // {value: "Tom", done: false}

При обращении к свойству value полученного из промиса получить сами данные:

const personGenerator = generatePersonAsync();
personGenerator.next()
.then(data => console.log(data.value));  // Tom

С помощью оператора await из метода next() генератора мы можем получить данные:

async function* generatePersonAsync() {
  yield "Tom";
  yield "Sam";
  yield "Bob";
}
async function printPeopleAsync() {
  const personGenerator = generatePersonAsync();
  while (!(person = await personGenerator.next()).done) {
    console.log(person.value);
  }
}
printPeopleAsync();

Консольный вывод:

Tom
Sam
Bob

Поскольку асинхронный генератор представляет асинхронный итератор, то данные генератора также можно получить через цикл for-await-of:

async function* generatePersonAsync() {
  yield "Tom";
  yield "Sam";
  yield "Bob";
}
async function printPeopleAsync() {
  const personGenerator = generatePersonAsync();
  for await (person of personGenerator) {
    console.log(person);
  }
}
printPeopleAsync();
// Tom
// Sam
// Bob

await в асинхронных генераторах

Главным преимуществом асинхронным генераторов является то, что мы можем использовать в них оператор await и соответственно получать данные из источников данных, которые используют асинхронный API:

async function* generatePersonAsync(people) {
  for (const person of people) yield await new Promise((resolve) => setTimeout(() => resolve(person), 2000));
}
async function printPeopleAsync(people) {
  for await (const item of generatePersonAsync(people)) {
    console.log(item);
  }
}
printPeopleAsync(["Tom", "Sam", "Bob"]);

Здесь для имитации получения данных из асинхронного источника данных применяется промис, который через 2000 секуд возвращает один из элементов массива, который передается в функцию генератора:

yield await new Promise(resolve => setTimeout(() => resolve(person), 2000));
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг