Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to reset an ECMAScript 6 generator to its initial state?

Given the provided (very simple) generator, is it possible to return the generator back to its original state to use again?

var generator = function*() {     yield 1;     yield 2;     yield 3; };  var iterable = generator();  for (let x of iterable) {     console.log(x); }  // At this point, iterable is consumed. // Is there a method for moving iterable back // to the start point by only without re-calling generator(), // (or possibly by re-calling generator(), only by using prototype  //  or constructor methods available within the iterable object) // so the following code would work again?  for (let x of iterable) {     console.log(x); } 

I would like to be able to pass the iterable off to some other scope, iterate over it, do some other stuff, then be able to iterate over it again later on in that same scope.

like image 773
dvlsg Avatar asked May 24 '14 17:05

dvlsg


People also ask

What is an ES6 generator?

Generator (or Generator function) is the new concept introduced in ES6. It provides you a new way of working with iterators and functions. ES6 generator is a different kind of function that may be paused in the middle either one or many times and can be resumed later.

What does generator return JavaScript?

A return statement in a generator, when executed, will make the generator finish (i.e. the done property of the object returned by it will be set to true ). If a value is returned, it will be set as the value property of the object returned by the generator.

How do JavaScript generators work?

In ECMAScript 2015, generators were introduced to the JavaScript language. A generator is a process that can be paused and resumed and can yield multiple values. A generator in JavaScript consists of a generator function, which returns an iterable Generator object.


2 Answers

If your intention is

to some other scope, iterate over it, do some other stuff, then be able to iterate over it again later on in that same scope.

Then the only thing you shouldn't try doing is passing the iterator, instead pass the generator:

var generator = function*() {     yield 1;     yield 2;     yield 3; };  var user = function(generator){      for (let x of generator()) {         console.log(x);     }      for (let x of generator()) {         console.log(x);     } } 

Or just make a "round robin" iterator and check while iterating

var generator = function*() {     while(true){         yield 1;         yield 2;         yield 3;     } };  for( x in i ){     console.log(x);     if(x === 3){         break;     } } 
like image 187
Azder Avatar answered Oct 18 '22 15:10

Azder


At this point, iterable is consumed.

Which means its internal [[GeneratorState]] is completed.

Is there a method for moving iterable back to the start point by only without re-calling generator()

No. The spec states

Once a generator enters the "completed" state it never leaves it and its associated execution context is never resumed. Any execution state associated with generator can be discard at this point.

or possibly by re-calling generator(), only by using prototype or constructor methods available within the iterable object

No. While not explicitly stated in the spec, there are no more instance-specific properties available on the iterable object than [[GeneratorState]] and [[GeneratorContext]].

However, the informative "Generator Object Relationships" grapic states:

Each Generator Function has an associated prototype that does not have a constructor property. Hence a generator instance does not expose access to its generator function.

I would like to be able to pass the iterable off to some other scope

Pass the generator function instead. Or something that yields new generator instances.

like image 35
Bergi Avatar answered Oct 18 '22 14:10

Bergi