Created
July 22, 2020 15:49
-
-
Save paulmelero/c3f00a87cd97ea8a93509f7c34a666b2 to your computer and use it in GitHub Desktop.
Async once
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
/** | |
* Takes a generator function that can yeild async functions. | |
* When the wrapped generator is called again, the previous call will cancel ASAP. | |
* Note: it won't cancel in-flight requests made (see: AbortController) | |
* @param {GeneratorFunction} generator | |
* @see https://dev.to/chromiumdev/cancellable-async-functions-in-javascript-5gp7 | |
* @author Sam Thorogood | |
* @returns {(...args: any[]) => Promise<any>} | |
*/ | |
export const asyncOnce = generator => { | |
let globalNonce | |
return async function(...args) { | |
const localNonce = new Object() | |
globalNonce = localNonce | |
const iter = generator(...args) | |
let resumeValue | |
for (;;) { | |
const n = iter.next(resumeValue) | |
if (n.done) { | |
return n.value // final return value of passed generator | |
} | |
// whatever the generator yielded, _now_ run await on it | |
resumeValue = await n.value | |
if (localNonce !== globalNonce) { | |
return // a new call was made | |
} | |
// next loop, we give resumeValue back to the generator | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment