Почему мой генератор становится пустым после повторения? - PullRequest
2 голосов
/ 28 июня 2019

У меня есть генератор, возвращаемый мне вызовом функции из библиотеки, которую я использую. Затем я передаю этот генератор функции, которая перебирает его и выполняет кучу логики для каждого из элементов. Затем я хочу обратиться к тому же генератору после вызова этой функции. Тем не менее, кажется, что генератор больше не имеет / генерирует какие-либо предметы. Код выглядит следующим образом:

let myGenerator = this.generatorFunc();
console.log(Array.from(myGenerator).length); //prints N which is specified elsewhere
this.iterateThroughGenerator(myGenerator);
console.log(Array.from(myGenerator).length); //now prints 0 when I need it to be N still

iterateThroughGenerator(generator) {
    for(let element of generator) {
        // do a bunch of stuff with element
    }
}

Ответы [ 4 ]

1 голос
/ 28 июня 2019

Другие уже объяснили , почему это происходит, но я все равно повторю.

Функции генератора возвращают объект генератора , который реализует итерационный протокол (свойство Symbol.iterator) с использованием простого циклическая ссылка на себя и протокол итератора (метод next()), чтобы выполнить итерацию по ходу управляющего потока своей функции генератора.

Чтобы решить вашу проблему, инкапсулируйте вызов функции генератора с объектом, который реализует итеративный протокол, возвращая отдельные экземпляры вашего объекта генератора, и вы можете использовать его таким же образом:

const iterable = { [Symbol.iterator]: () => this.generatorFunc() };

console.log(Array.from(iterable).length); //prints N which is specified elsewhere
this.iterateThroughGenerator(iterable);
console.log(Array.from(iterable).length); //still prints N

iterateThroughGenerator(iterable) {
    for(let element of iterable) {
        // do a bunch of stuff with element
    }
}
1 голос
/ 28 июня 2019

Так работают итераторы. Вызов генератора возвращает итератор, который можно повторить один раз. То же самое в большинстве других языков.

let generator = function* () {
  for (let i = 0; i < 3; i++) 
    yield i;
};

let iterator = generator();

console.log(Array.from(iterator)); // [1...3]
console.log(Array.from(iterator)); // []

console.log(Array.from(generator())); // [1..3]
console.log(Array.from(generator())); // [1..3]
0 голосов
/ 28 июня 2019

Array.from() истощает генератор (повторяя его до конца), и повторяя его дальше, вы не получите больше элементов. next() звонки всегда будут возвращаться {value: undefined, done: true}.

Чтобы создать новый генератор, который снова запускается с самого начала, вам нужно снова вызвать generatorFunc().

0 голосов
/ 28 июня 2019

Как только функция генератора завершена, вы должны вызвать this.getGeneratorFunc (), чтобы заново создать генератор. Кроме того, когда вы выполняете Array.from (myGenerator), он также завершает этот генератор, поэтому, когда вы вызываете this.iterateThroughGenerator (myGenerator), тогда ничего не произойдет, потому что больше нет элементов, возвращаемых из генератора. Таким образом, вы можете либо сохранить результат генератора в массив и повторно использовать этот массив, либо вызывать this.getGeneratorFunc () три раза каждый раз, когда вы хотите получить из него элементы. В этом конкретном примере я бы сделал

 const generated = Array.from(this.getGeneratorFunc());
 console.log(generated.length);
 this.iteratedItems(generated);
 console.log(generated.length);

Проверьте и этот ответ. Предыдущий ответ
Я также прочитал это .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...