Skip to content

Instantly share code, notes, and snippets.

@padcom
Last active July 7, 2025 08:40
Show Gist options
  • Save padcom/44ab0edcea7ee6818c68ae66b7c80e27 to your computer and use it in GitHub Desktop.
Save padcom/44ab0edcea7ee6818c68ae66b7c80e27 to your computer and use it in GitHub Desktop.
wait-for and sleep with interruption implementation using AbortSignal
let count = 0
try {
console.log(await waitFor(async () => {
console.log('cb: sleep', await sleep(100))
return ++count == 3
}))
} catch (e) {
console.log(e)
}
console.log(await sleep(2000))
/**
* Sleep with the option to stop sleeping upon a signal
*
* @param {Number} ms timeout
* @param {AbortSignal} signal
*/
function sleep(ms, signal = undefined) {
return new Promise(resolve => {
const done = () => {
signal?.removeEventListener('abort', abort)
resolve('done')
}
const timeout = setTimeout(done, ms)
const abort = () => {
clearTimeout(timeout)
resolve('aborted')
}
signal?.addEventListener('abort', abort)
})
}
/**
* Periodically check the given callback at the specified interval
* if it returns a truthy value.
* If it doesn't then abort the wait after the given timeout ms
*
* @param {Function} cb
* @param {Number} timeout
* @param {Number} interval
* @param {AbortSignal} signal
*/
async function waitFor(cb, timeout = 1000, interval = 100, signal = undefined) {
const interrupt = AbortSignal.any([AbortSignal.timeout(timeout), signal].filter(x => x))
return new Promise((resolve, reject) => {
const work = async () => {
const result = await cb()
if (result) {
clearInterval(timer)
interrupt?.removeEventListener('abort', abort)
resolve(result)
}
}
const timer = setInterval(work, interval)
const abort = () => {
clearInterval(timer)
reject('timeout')
}
interrupt?.addEventListener('abort', abort)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment