Async Iteration and Generators
Generators, Advanced Iteration: Async Iteration and Generators
What are some popular applications for asynchronous iteration in JavaScript?
View Answer:
Interview Response: When there is an asynchronous need to retrieve data, we typically use asynchronous iteration. The most common use case is an object needs to make a network request to deliver the next value. This approach is also a great way to handle controlled chunks of data to reduce the impact on resources.
Code Example:
let range = {
from: 1,
to: 5,
[Symbol.asyncIterator]() {
// (1)
return {
current: this.from,
last: this.to,
async next() {
// (2)
// note: we can use "await" inside the async next:
await new Promise((resolve) => setTimeout(resolve, 1000)); // (3)
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
},
};
(async () => {
for await (let value of range) {
// (4)
alert(value); // 1,2,3,4,5
}
})();
Is it possible to use a spread syntax with an asynchronous iterator?
View Answer:
Interview Response: No, because the spread syntax expects to find Symbol.iterator, not Symbol.asyncIterator. It’s also the case for for..of: the syntax without await needs Symbol.iterator.
Code Example:
// The Spread Syntax works with Symbol.iterator (That's what its look for...)
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
// called once, in the beginning of for..of
return {
current: this.from,
last: this.to,
next() {
// called every iteration, to get the next value
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
},
};
console.log([...range]); // [1,2,3,4,5] It works!!!
////////////////////////////////////
// Spread Syntax fails with Symbol.asyncIterator
let range = {
from: 1,
to: 5,
[Symbol.asyncIterator]() {
// (1)
return {
current: this.from,
last: this.to,
async next() {
// (2)
// note: we can use "await" inside the async next:
await new Promise((resolve) => setTimeout(resolve, 1000)); // (3)
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
},
};
console.log([...range]); // Error, no Symbol.iterator