логотип PurpleSchool
Иконка входа
Вход
  • Обучение
  • Войти
логотип PurpleSchool

Генераторы в JavaScript

Автор

Дмитрий Нечаев

Генераторы в JavaScript — это особый тип функций, который поддерживает приостановку и возобновление выполнения, при этом сохраняя контекст между последовательными вызовами. Генераторы используются для упрощения работы с асинхронным кодом, обработки потоков данных и реализации пользовательских итераторов. Возвращаемый генератором объект итерируем и поддерживает интерфейс итератора.

Основы генераторов

Генератор объявляется с помощью ключевого слова function* (звездочка после слова function). Тело генератора содержит одну или несколько инструкций yield, которые указывают, на каком месте функция должна быть приостановлена.

function* numberGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = numberGenerator(); // Создание генератора

console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().value); // undefined, генератор завершил своё выполнение

Методы объекта-генератора

Каждый генератор имеет следующие методы:

  • next(): возобновляет выполнение функции до следующей точки yield или до конца функции, если yield больше нет.
  • return(value): прекращает выполнение генератора и возвращает указанное значение.
  • throw(error): возобновляет выполнение генератора и передает ошибку внутрь генератора.
function* genFunc() {
  try {
    yield 1;
    yield 2;
  } catch(e) {
    console.log(e);
  }
}

const gen = genFunc();
console.log(gen.next().value); // 1
gen.throw('Произошла ошибка'); // Выведет "Произошла ошибка" и завершит выполнение

Передача значений через yield

Генераторы могут не только возвращать значения, но и получать их через yield. Это позволяет организовать двустороннюю коммуникацию между генератором и его вызывающим кодом.

function* interactiveGen() {
  const input = yield "Введите данные";
  yield `Вы ввели: ${input}`;
}

const gen = interactiveGen();
console.log(gen.next().value); // "Введите данные"
console.log(gen.next('Пример данных').value); // "Вы ввели: Пример данных"

Использование генераторов для управления асинхронным кодом

Генераторы могут быть использованы для управления асинхронным кодом, особенно в сочетании с промисами и асинхронными операциями.

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

function* asyncFlow() {
  console.log('Начало');
  yield delay(1000);
  console.log('Конец');
}

const gen = asyncFlow();
const promise = gen.next().value; // Начало
promise.then(() => gen.next());

Генераторы для создания итерируемых структур

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

function* range(start, end) {
  for (let i = start; i <= end; i++) {
    yield i;
  }
}

const r = range(1, 5);
for (const num of r) {
  console.log(num); // Выведет числа от 1 до 5

}

Заключение

Генераторы в JavaScript — это мощный инструмент для создания функций, которые можно приостанавливать и возобновлять, что особенно полезно для управления асинхронными операциями и создания итерируемых структур. Благодаря своей гибкости и возможности взаимодействия с вызывающим кодом, генераторы открывают широкие возможности для реализации сложной логики в вашем JavaScript-коде.

Карта развития разработчика

Получите полную карту развития разработчика по всем направлениям: frontend, backend, devops, mobile