I have a code like this:
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function* foo() {
yield 1;
await delay(100);
yield 2;
await delay(100);
yield 3;
await delay(100);
yield 4;
await delay(100);
yield 5;
await delay(100);
yield 6;
await delay(100);
yield 7;
await delay(100);
yield 8;
await delay(100);
yield 9;
await delay(100);
yield 10;
}
async function* bar() {
yield 'a';
await delay(200);
yield 'b';
await delay(200);
yield 'c';
await delay(200);
yield 'd';
await delay(200);
yield 'e';
}
(async function () {
for await (const num of foo()) {
console.log(num);
}
for await (const str of bar()) {
console.log(str);
}
await delay(2000);
})();
which produce:
1
2
3
4
5
6
7
8
9
10
a
b
c
d
e
What addjustments I should make, to read from 2 generators at the same time, and get:
1
2
a
3
4
b
5
6
c
7
8
d
9
10
e
In a comment you said:
I get 2 generators as output from libary which run a binary. One generator is with output (lines of texts, each line yielded at a time), and another generator contains information about progress (numbers from 0 to 100). Of course I want to be able to display progress simultaneously while displaying output.
In that case, loop through the async generators in parallel:¹
async function show(g) {
for await (const value of g) {
console.log(value);
}
}
(async function () {
// Start processing the first one
const pFoo = show(foo());
// Start processing the second one
const pBar = show(bar());
// Wait until both are done
await Promise.all([pFoo, pBar]);
})();
But, note that if you do that with the specific two synthetic generators in your question, the output won't be exactly what you've said you wanted, because foo writes 1 synchronously before waiting 100ms, and similarly bar writes a synchronously before waiting 200ms, so the results start with 1 a 2 b and then continue with 3 4 c 5 6 d 7 8 e and so on. They are interleaved as you've said you wanted, just those synthetic ones don't quite have the timing you were expecting when writing the question.
Live Example:
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function* foo() {
yield 1;
await delay(100);
yield 2;
await delay(100);
yield 3;
await delay(100);
yield 4;
await delay(100);
yield 5;
await delay(100);
yield 6;
await delay(100);
yield 7;
await delay(100);
yield 8;
await delay(100);
yield 9;
await delay(100);
yield 10;
}
async function* bar() {
yield "a";
await delay(200);
yield "b";
await delay(200);
yield "c";
await delay(200);
yield "d";
await delay(200);
yield "e";
}
async function show(g) {
for await (const value of g) {
console.log(value);
}
}
(async function () {
const pFoo = show(foo());
const pBar = show(bar());
await Promise.all([pFoo, pBar]);
})();
.as-console-wrapper {
max-height: 100% !important;
}
¹ "Parallel" in async terms. They don't literally run in parallel threads, they interleave (sort of like "cooperative multitasking"). JavaScript restricts its execution semantics to only a single active thread within a given realm ("realm" loosely means global environment and the code in it).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With