Skip to content

Instantly share code, notes, and snippets.

@denk0403
Last active April 28, 2023 05:43
Show Gist options
  • Save denk0403/d13e34301329bf6883272a1a6d8e2478 to your computer and use it in GitHub Desktop.
Save denk0403/d13e34301329bf6883272a1a6d8e2478 to your computer and use it in GitHub Desktop.
Cancellable Events and Promises
/**
* @param {EventTarget} target
* @param {string} eventType
* @param {number?} delayInMs
* @returns {Promise<Event>}
*/
function eventTimeout(target, eventType, delayInMs = null) {
const abortController = new AbortController(),
signal = abortController.signal;
let timer;
if (typeof delayInMs === "number") {
timer = setTimeout(() => {
if (!signal.aborted)
abortController.abort(new Error(`${eventType} was not fired within ${delayInMs}ms.`));
}, delayInMs);
}
return cancellableEvent(target, eventType, signal).finally(() => clearTimeout(timer));
}
/**
* @param {EventTarget} target
* @param {string} eventType
* @param {AbortSignal?} signal
* @returns {Promise<Event>}
*/
function cancellableEvent(target, eventType, signal = null) {
return new Promise((res, rej) => {
if (signal) signal.onabort = () => rej(signal.reason);
target.addEventListener(eventType, (event) => res(event), {
once: true,
signal,
});
});
}
/**
* @param {Promise} promise
* @param {number?} delayInMs
* @returns {Promise}
*/
function promiseTimeout(promise, delayInMs = null) {
const abortController = new AbortController(),
signal = abortController.signal;
let timer;
if (typeof delayInMs === "number") {
timer = setTimeout(() => {
if (!signal.aborted)
abortController.abort(new Error(`The Promise was not resolved within ${delayInMs}ms.`));
}, delayInMs);
}
return cancellablePromise(promise, signal).finally(() => clearTimeout(timer));
}
/**
* @param {Promise} promise
* @param {AbortSignal?} signal
* @returns {Promise}
*/
function cancellablePromise(promise, signal = null) {
return new Promise((res, rej) => {
if (signal) signal.onabort = () => rej(signal.reason);
promise.then(res).catch(rej);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment