What is the difference between synchronous and asynchronous generators?
Assesses fundamental understanding of JavaScript conventions, runtime behavior, and memory/performance considerations.
Hiring managers look for precision, avoidance of ambiguous jargon, and ability to explain trade-offs under real production conditions.
Synchronous and asynchronous generators differ in how they produce values and handle asynchronous operations.
Synchronous generator:
function* syncGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = syncGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
Asynchronous generator:
async function* asyncGenerator() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
yield await Promise.resolve(3);
}
(async () => {
for await (const value of asyncGenerator()) {
console.log(value); // 1, 2, 3
}
})();
Comparison:
| Synchronous Generator | Asynchronous Generator |
|----------------------|------------------------|
| function* | async function* |
| Returns iterator | Returns async iterator |
| .next() returns { value, done } | .next() returns Promise<{ value, done }> |
| Used with for...of | Used with for await...of |
| Cannot await inside | Can await inside |
Practical example - data streaming:
// Sync generator - in-memory data
function* readFileSync(lines) {
for (const line of lines) {
yield line;
}
}
// Async generator - streaming data
async function* readFileAsync(filePath) {
const stream = createReadStream(filePath);
const reader = stream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
yield value;
}
}
Async generator with delays:
async function* ticker(interval, max) {
let count = 0;
while (count < max) {
await new Promise(resolve => setTimeout(resolve, interval));
yield count++;
}
}
(async () => {
for await (const tick of ticker(1000, 5)) {
console.log(tick); // 0, 1, 2, 3, 4 (one per second)
}
})();
Combining generators:
async function* fetchPages(urls) {
for (const url of urls) {
const response = await fetch(url);
yield await response.json();
}
}
async function* processPages(urls) {
for await (const page of fetchPages(urls)) {
yield processPage(page);
}
}
Candidate Response Strategy & Interview Tips
- Start with a concise one-sentence summary: Deliver a direct, confident answer first before expanding into nuances.
- Demonstrate real-world trade-offs: Discuss where this approach excels and when you would avoid it in production systems.
- Discuss complexity & edge cases: Proactively explain time/space complexity or boundary conditions (null values, scale limits).
- Prepare for interviewer follow-ups: Technical hiring panels frequently probe deeper into concurrency, backward compatibility, or alternative libraries.