Генераторы¶
function *
- это синтаксис, используемый для создания функции генератора. Вызов функции генератора возвращает объект генератора. Объект генератора просто реализует интерфейс iterator (а именно функции next
, return
и throw
).
Существуют 2 основные причины использовать функции генератора:
Ленивые итераторы¶
Функции генератора могут использоваться для создания ленивых итераторов, например, следующая функция возвращает бесконечный список целых чисел по запросу:
1 2 3 4 5 6 7 8 9 10 11 |
|
Конечно, если итератор завершится, вы получите результат {done: true}
, как показано ниже:
1 2 3 4 5 6 7 8 9 10 11 |
|
Внешнее контролируемое исполнение¶
Это та роль генераторов, которая действительно восхищает. По сути, это позволяет функции приостановить выполнение и передать управление оставшейся части функции вызывающей стороне.
Функция генератора не выполняется при вызове. Она просто создает объект генератора. Рассмотрим следующий пример вместе с примером выполнения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Если вы запустите это, вы получите следующий вывод:
1 2 3 4 5 6 7 8 |
|
- Функция начинает выполнение только после вызова
next
объекта-генератора. - Функция делает паузу, как только встречается оператор yield.
- Функция возобновляется при вызове
next
.
Так что, по сути, выполнение функции генератора контролируется объектом генератора.
Наше общение с использованием генератора было в основном односторонним, когда генератор возвращал значения для итератора. Одна чрезвычайно мощная особенность генераторов в JavaScript состоит в том, что они допускают двустороннюю связь!
- Вы можете контролировать результирующее значение выражения
yield
, используяiterator.next(valueToInject)
- вы можете бросить исключение в выражении
yield
, используяiterator.throw(error)
В следующем примере демонстрируется iterator.next(valueToInject)
:
1 2 3 4 5 6 7 8 9 10 11 |
|
В следующем примере демонстрируется iterator.throw(error)
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Итак, вот резюме:
yield
позволяет функции генератора приостанавливать выполнение и передавать управление внешней системе- внешняя система может передать значение в тело функции генератора
- внешняя система может бросить исключение в тело функции генератора
И чем это может быть полезно? Перейдите к следующему разделу async/await и узнайте.