Last active
January 3, 2020 20:23
-
-
Save hugosenari/566d72bd61385be55f087a48608b3e0c to your computer and use it in GitHub Desktop.
JS Async Generator Race
This file contains hidden or 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
const genToAsyncGen = async iteration => ({ | |
value: await (await iteration).value, | |
done: (await iteration).done, | |
}); | |
const iterableToIterator = (iterable = []) => { | |
if (iterable[Symbol.asyncIterator]) | |
return iterable[Symbol.asyncIterator](); | |
if (iterable[Symbol.iterator]) | |
return iterable[Symbol.iterator](); | |
if (iterable.next) return iterable; | |
return [].values(); | |
} | |
// works with iterable and asyncIterable | |
exports.asRace = (concurrencyLimit = 10) => ( | |
async function* innerRace(iterable) { | |
const iterator = iterableToIterator(iterable); | |
let numWorkers = concurrencyLimit; | |
const workInProgress = new Set(); | |
const finished = new Set(); | |
do { | |
while (workInProgress.size !== numWorkers) { | |
const task = genToAsyncGen( | |
iterator.next() | |
); | |
workInProgress.add(task); | |
task.then(({ done, value }) => { | |
workInProgress.delete(task); | |
if (done) numWorkers -= 1; | |
else finished.add(value); | |
}).catch(e => { | |
workInProgress.delete(task); | |
finished.add(e) | |
}); | |
} | |
if (workInProgress.size) | |
await Promise.race(workInProgress); | |
yield * finished; | |
finished.clear(); | |
} while (numWorkers); | |
} | |
); | |
const toPromise = async value => value; | |
// works only with iterable | |
async function* sortByResolution(iterable) { | |
const inProgress = new Set(iterable); | |
const finished = new Set(); | |
do { | |
Array.from(inProgress).map(task => toPromise(task) | |
.then(v => finished.add(v)) | |
.catch(e => finished.add(e)) | |
.finally(() => inProgress.delete(task))); | |
if (inProgress.size) { | |
await Promise.race(inProgress); | |
} | |
yield * finished; | |
finished.clear(); | |
} while (inProgress.size); | |
} | |
exports.sortByResolution = sortByResolution; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment