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

Последнее обновление: 04.09.2021

Асинхронные итераторы открывают нам путь к созданию асинхронных генераторов. Асинхронные генераторы позволяют нам использовать оператор 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));
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850