Немного о генераторах
У генераторов есть одна большая проблема — когда кто-то пытается про них писать, прочитать это с первого раза совершенно невозможно. Я как мог пытался сделать это доступно. Ну, поехали.
Как и асинки, генераторы позволяют писать асинхронный код без вызова колбеков.
Функция-генератор обозначается *
звездочкой.
В отличие от обычных функций, при вызове функции-генератора не будет выполнено ее тело, а вернется, собственно, генератор.
Пока он на паузе. Для начала работы нужно вызвать метод next
. Код будет выполнен до следующего yield
, там переданное в оператор значение отправится наружу внутри специальной структуры, где будет value
(наше значение) и done
(жив ли еще генератор).
Как и await
в асинках, yield
работает только внутри генератора.
не пытайтесь йелдить в колбеке
Зато знаете, что можно? Циклы! Бесконечный генератор? Легко!
Вернемся к первому примеру.
Завершение работы генератора отмечает return
. В принципе, его можно не писать, но тогда последнийvalue
вернется с undefined
.
Когда весь код в теле функции будет выполнен, done
станет true
. Все последующие next будут возвращать undefined
. На этом наш генератор официально отработал свое, несите другой.
Идем дальше. Генераторы могут работать в обе стороны. Для этого нужно передать значение в next
.
Поскольку первый next
только запускает процесс, передавать туда что-либо бессмысленно. Зато следующий yield
уже получит значение.
Попробуем вызвать генератор внутри генератора:
Выглядит так себе. Специально для таких случаев придумали yield*
, который позволяет запускать генераторы из генераторов без лишней мороки. Как говорится, Yo Dawg.
Обратите внимание, что значение из return
нужно присвоить, оно не зайелдится само по себе.
Интересно, что кроме самого генератора через *
можно зайелдить массив.
Что общего между генератором и массивом? Они оба итерируемы! А это значит, что мы можем использовать for…of
.
Значения больше не нужно вытаскивать из поля value
, но return
при выдаче не учитывается.
Бесконечный генератор в одном из прошлых примеров тоже можно проитерировать, но он повесит вам браузер, очевидно.
Примечательно, что генераторы можно спредить и деструктурировать, при чем во втором случае это можно делать даже на бесконечных генераторах, поскольку мы берем конечное количество значений.
И еще один момент: кроме next
у генератора также есть методы return
и throw
. Они оба работают по аналогии с одноименными операторами. После их вызова генератор остановится.
С поддержкой у генераторов даже лучше, чем с асинками, но, естественно, без IE (гори он огнем).
Ну а за полифил, опять же, отвечает библиотека regenerator. Собственно, внутри асинки построены на том же механизме.
Подробнее:
1. Exploring ES6
2. Современные возможности ES-2015
3. EcmaScript-262 6th Edition
4. co
5. redux-saga