Resetable JavaScript Generators

What if you could re-use a JavaScript generator instance by just calling <generator>.reset()? So long as you understand Proxies, with just a few lines of code you can write a wrapper function that will support this!

Resetable Generators

Making a generator resetable requires wrapping the function with anapply Proxy that does two things:

  1. remembers the arguments to the original creation of the generator
  2. re-defines next() to use a new version of the generator after reset() is called.
function resetableGenerator(f) {
const proxy = new Proxy(f,{
apply(target,thisArg,argumentsList) {
const base = target.call(thisArg,...argumentsList),
basenext = base.next;
let generator = base;
base.next = function next() {
return generator===base
? basenext.call(base) // generator is the original one
: generator.next(); // generator is the reset one
}
// define reset to use the original arguments to create
// a new generator and assign it to the generator variable
Object.defineProperty(generator,"reset",{
enumerable:false,
value: () =>
generator = target.call(thisArg,...argumentsList)
});
// return the generator, which now has a reset method
return generator;
}
});
// return proxy which will create a generator with a reset method
return proxy;
}

You can test the code using the below script:

function* myGenerator(values) {
for(const value of values) yield value;
}
myGenerator = resetableGenerator(myGenerator);
let generator = myGenerator([1,2,3]);
for(const value of generator) {
const el = document.createElement("div");
el.innerText = value;
document.body.appendChild(el)
}
// comment out reset and 123 will only be shown once
generator.reset();
for(const value of generator) {
const el = document.createElement("div");
el.innerText = value;
document.body.appendChild(el)
}

Here is a JSFiddle to see the code in action.

I hope you found this useful. Watch for the next article where generators are given memory so they can be accessed like arrays!

If you would like a generator library that implements the above for both synchronous and asycnhronous generators plus provides full forEach, every, some, slice, and other array like operations try generx. You can also read more about generx at Next Generation JavaScript Generators.