Skip to content

Instantly share code, notes, and snippets.

@gangsthub
Created July 22, 2020 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gangsthub/c3f00a87cd97ea8a93509f7c34a666b2 to your computer and use it in GitHub Desktop.
Save gangsthub/c3f00a87cd97ea8a93509f7c34a666b2 to your computer and use it in GitHub Desktop.
Async once
/**
* 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