Iterables and Generators Flashcards
What are Iterables
Iterables are objects that have the method
~~~
[Symbol.Iterator]: () => ({
next(): { value: any, done: boolean};
})
~~~
Then methods that iterate work by calling next() until done is true.
What are generators
Generators are special functions that behave differently from regular functions - the body isn’t run when called. Instead, they return a generator object to manage the execution.
The main method of a generator is next(). When called, it runs the execution until the nearest yield and returns { value, done: boolean }
// Simple generator function* generateSequence(start, end) { for (let i = start; i <= end; i++) yield i; } //Compound generator function* generatePasswordCodes() { yield* generateSequence(48, 57); yield* generateSequence(65, 90); yield* generateSequence(97, 122); }
What’s the output of the following code?
function* generateSequence() { yield 1; yield 2; return 3; } let generator = generateSequence(); for(let value of generator) { alert(value); }
1,2
Generators return an object that is compatible with Iterator method, so they can be iterated over.
However only yield statements are considered, so return 3 is not included.
Since generator functions are essentially the same as Iterator, the following objects are equivalent:
// First object
let range = {
from: 1,
to: 5,
Symbol.iterator {
return {
current: this.from,
last: this.to,
next() { if (this.current <= this.last) { return { done: false, value: this.current++ }; } else { return { done: true }; } } }; } };
// Second object
let range = {
from: 1,
to: 5,
*Symbol.iterator {
for(let value = this.from; value <= this.to; value++) {
yield value;
}
}
};
alert( […range] ); // 1,2,3,4,5
What is the output of the following code?
function* gen() { // Pass a question to the outer code and wait for an answer let result = yield "2 + 2 = ?"; // (*) alert(result); } let generator = gen(); let question = generator.next().value; //(1) const answer = prompt(question, 4); generator.next(answer); //(2)
4
‘yield’ is a two way street, is not only produces data(since its value is included in generator object), it can also consume data as it acts a placeholder for receiving any data if .next() is called with a value.
So:
At (1), next() is called which goes to the nearest yield statement and returns { value: “2+2 = ?”, done: false } and pauses.
At (2), we call next(4), and since we left of at (*), result is assigned to 4, and 4 is alerted.
What are async iterables?
Async Iterables are objects that have the method
[Symbol.asyncIterator]: () =>({ async next(): Promise; })
Then you can loop using for await(const .. of)
Note since [Symbol.asyncIterator] !== [Symbol.Iterator], methods like spreading are not available.
What are async generators
Async generators return a generator object { async next(): Promise }
async function* generateSequence(start, end) { for (let i = start; i <= end; i++) { // Wow, can use await! await new Promise(resolve => setTimeout(resolve, 1000)); yield i; } }