Iterator
While they get most of the work done, there is often we want to iterate these collections of data at convince, getting the next data from the collection at the method invocation.
function createIterator(arr) {
let index = 0;
return {
next() {
if (index < arr.length) {
const ans = { value: arr[index], done: false };
index += 1;
return ans;
} else {
return { value: null, done: true };
}
},
};
}
const iterator = createIterator([1, 2, 3]);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
// { value: 1, done: false }
// { value: 2, done: false }
// { value: 3, done: false }
// { value: null, done: true }
Creating iterators using Generator functions in JavaScript
function* Gen(arr) {
yield* [...arr];
}
const g = Gen([1, 2, 3]);
console.log(g.next());
console.log(g.next());
console.log(g.next());
console.log(g.next());
// { value: 1, done: false }
// { value: 2, done: false }
// { value: 3, done: false }
// { value: undefined, done: true }
Creating iterators using Symbol.iterator static method
const g = {};
g[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
console.log([...g]); // [1,2,3]
We can use the Generators functions to create iterators that will iterate only once.
function* CreateIterator1(arr) {
yield* [...arr];
}
const iterator = CreateIterator1([1, 2, 3]);
for (const item of iterator) {
console.log(item);
}
// 1 2 3
for (const item of iterator) {
console.log(item);
}
//
While multiple iterable iterators can be created using Symbol.iterator
const g = {};
g[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
for (const item of g) {
console.log(item);
}
// 1 2 3
for (const item of g) {
console.log(item);
}
// 1 2 3
Round Robin
For example, assume you are assigning values based on the round-robin principle on each invocation, you can pass the value to the next()
method to reset it at any point.
We can use singleton pattern along with the iterator and share the round-robin logic throughout the application code.
function* RoundRobin(collection) {
let current = 0;
while (true) {
const reset = yield collection[current++ % collection.length];
if (reset) {
current = 0;
}
}
}
const rr = RoundRobin([1, 2, 3, 4]);
console.log(rr.next()); //{"value": 1, "done": false }
console.log(rr.next()); //{"value": 2, "done": false }
console.log(rr.next()); //{"value": 3, "done": false }
console.log(rr.next(true)); //{"value": 1, "done": false } // reset's the counter
console.log(rr.next()); //{"value": 2, "done": false }
console.log(rr.next()); //{"value": 3, "done": false }
console.log(rr.next()); //{"value": 4, "done": false }
console.log(rr.next()); //{"value": 1, "done": false }
console.log(rr.next()); //{"value": 2, "done": false }