Generators: yield, next(), return()

Генераторы: магия, которая делает итераторы простыми ✨

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

function* simpleGenerator() {
  yield 1;
  yield 2;
  return 3;
}

🔍 Ключевой момент: звёздочка (*) после function — это не просто синтаксис. Она говорит движку: «Эта функция — особенная, запомни её».


Как работают yield и next()

Генератор не выполняется сразу при вызове. Вместо этого он возвращает объект-итератор с методами:

  • next() — запускает выполнение до ближайшего yield или return
  • return() — принудительно завершает генератор
  • throw() — вызывает ошибку внутри генератора (но это уже продвинутая тема)
const gen = simpleGenerator();

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: true }

Жизненный цикл генератора в деталях

  1. Создание
    Генератор «замораживается» на старте. Код не выполняется.

  2. Первый next()
    Движок доходит до первого yield, возвращает его значение и засыпает.

  3. Следующие вызовы
    Продолжает с места остановки до нового yield или return.

  4. Завершение
    После return или последнего yield свойство done становится true.


Пример: Бесконечная последовательность

Генераторы идеальны для работы с бесконечными данными — они вычисляют значения лениво (по запросу):

function* idGenerator() {
  let id = 0;
  while (true) {
    yield id++;
  }
}

const userIds = idGenerator();
console.log(userIds.next().value); // 0
console.log(userIds.next().value); // 1
// Можно вызывать бесконечно!

💡 Совет: такой подход экономит память — не нужно хранить весь массив ID.


Метод return(): аварийное завершение

Что, если нужно прервать генератор досрочно? Метод return() сделает это:

function* weatherControl() {
  yield '☀️ Солнечно';
  yield '🌧️ Дождь';
  yield '❄️ Снег';
}

const weather = weatherControl();
console.log(weather.next().value); // '☀️ Солнечно'
console.log(weather.return('🌀 Ураган')); // { value: '🌀 Ураган', done: true }
console.log(weather.next()); // { value: undefined, done: true }

После return() генератор переходит в состояние done: true и больше не работает.


Практика: Генератор случайных чисел с лимитом

Создадим генератор, который выдаёт случайные числа, но останавливается при превышении лимита:

function* randomGenerator(limit) {
  while (true) {
    const num = Math.floor(Math.random() * 10);
    if (num > limit) return 'Лимит превышен!'; // Выход
    yield num;
  }
}

const randomizer = randomGenerator(7);
console.log(randomizer.next()); // Например, { value: 3, done: false }
console.log(randomizer.next()); // { value: 7, done: false }
console.log(randomizer.next()); // Может вернуть { value: 'Лимит превышен!', done: true }

Где это применяется в реальности?

  1. Ленивые вычисления — данные обрабатываются только когда нужны.
  2. Асинхронные операции — вместе с async/await (но это отдельная история).
  3. Работа с деревьями — обход сложных структур данных.
  4. Redux-Saga — популярная библиотека для управления побочными эффектами.

Если хотите глубже разобрать асинхронные генераторы — посмотрите разборы Данилы Бежина на YouTube.


Итоговый чек-лист

  • Генераторы создаются через function*.
  • yield — ключевое слово для паузы.
  • next() — возобновляет выполнение.
  • return() — экстренная остановка.
  • Идеальны для обработки потоков данных.

Теперь вы умеете работать с одной из самых мощных возможностей JavaScript! 🚀

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео