resetableGenerator

by outis

JavaScript

function resetableGenerator(f) {
	function make(target, thisArg, argumentsList) {
		let generator = target.apply(thisArg, argumentsList),
			next = generator.next.bind(generator);
		return {generator, next};
  }

	const proxy = new Proxy(f,{
		apply(target,thisArg,argumentsList) {
			let { generator, next } = make(...arguments);
			generator.next = (value) => next(value);
			// 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, next} = make(...arguments)),
			});
			// return the generator, which now has a reset method
			return generator;
		},
	});
	// return proxy which will create a generator with a reset method
	return proxy;
}

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)
}