Last active
April 13, 2020 08:39
-
-
Save peter-leonov/f0c61dae5c8409030b8c3a192ddb63c4 to your computer and use it in GitHub Desktop.
Array<Promise<T>> -> AsyncIterator<T>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function main() { | |
async function f1() { | |
return new Promise((res) => { | |
setTimeout(() => { | |
res("1.1"); | |
}, 1000); | |
}); | |
} | |
async function f2() { | |
return new Promise((res) => { | |
setTimeout(() => { | |
res("2.1"); | |
}, 100); | |
}); | |
} | |
function streamManual(pArr) { | |
return { | |
[Symbol.asyncIterator]() { | |
// having this instead of a good promise queue with pushback | |
let promises = []; | |
let resolves = []; | |
let j = 0; | |
function done(value) { | |
resolves[j++]({ | |
done: false, | |
value, | |
}); | |
} | |
pArr.forEach((p) => { | |
p.then(done); | |
promises.push( | |
new Promise((res) => { | |
resolves.push(res); | |
}) | |
); | |
}); | |
let i = 0; | |
return { | |
next() { | |
if (i < pArr.length) { | |
return promises[i++]; | |
} else { | |
return Promise.resolve({ | |
done: true, | |
value: undefined, | |
}); | |
} | |
}, | |
}; | |
}, | |
}; | |
} | |
async function* streamNative(pArr) { | |
let resolve; | |
function done(v) { | |
resolve(v); | |
} | |
pArr.forEach((p) => p.then(done)); | |
for (let i = 0; i < pArr.length; i++) { | |
// It is safe to assume .next() will not be called while we are waiting, | |
// as the async gemerator has an internal queue for us: | |
// https://2ality.com/2016/10/asynchronous-iteration.html#queuing-next()-invocations | |
// https://www.typescriptlang.org/play?#code/IYZwngdgxgBAZgV2gFwJYHsICoYmQJwFNgBbARhgAoBKAbwCgYZ6BfIA | |
yield new Promise((res) => { | |
resolve = res; | |
}); | |
} | |
} | |
async function* runParallel(pArr) { | |
const res = new Array(pArr.length).fill(undefined); | |
for await (const [v, i] of streamManual( | |
pArr.map((p, i) => p.then((v) => [v, i])) | |
)) { | |
res[i] = v; | |
yield res; | |
} | |
} | |
// runParallel([f1(), f2()]); | |
for await (const results of runParallel([f1(), f2()])) { | |
console.log(results); | |
} | |
/** | |
* should output 2 lines: | |
* | |
* [undefined, "2.1"] // (after 100 ms) | |
* ["1.1", "2.1"] // (after 1000 ms) | |
*/ | |
} | |
main() | |
.then(() => { | |
console.log("done"); | |
}) | |
.catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment