Skip to content

Instantly share code, notes, and snippets.

@tkrotoff
Last active June 18, 2023 08:47
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 tkrotoff/c6dd1cabf5570906724097c6e3f65a12 to your computer and use it in GitHub Desktop.
Save tkrotoff/c6dd1cabf5570906724097c6e3f65a12 to your computer and use it in GitHub Desktop.
Cancelable await wait()
// https://gist.github.com/tkrotoff/c6dd1cabf5570906724097c6e3f65a12
// https://stackoverflow.com/a/67911932
export function wait(ms: number, options: { signal?: AbortSignal } = {}) {
const { signal } = options;
return new Promise<void>((resolve, reject) => {
// FIXME Not supported by Jest 29.3.1 + Node.js 19.3.0
//signal?.throwIfAborted();
if (signal?.aborted) reject(signal.reason);
const id = setTimeout(() => {
resolve();
// eslint-disable-next-line @typescript-eslint/no-use-before-define
signal?.removeEventListener('abort', abort);
}, ms);
function abort() {
clearTimeout(id);
reject(signal!.reason);
}
signal?.addEventListener('abort', abort);
});
}
import { assert } from './assert';
import { wait } from './wait';
test('wait without abort controller', async () => {
const start = performance.now();
await wait(10);
const end = performance.now();
expect(end - start).toBeGreaterThanOrEqual(9);
});
test('abort', () => {
const start = performance.now();
const waitController = new AbortController();
// eslint-disable-next-line jest/valid-expect-in-promise
wait(1000, { signal: waitController.signal })
.then(() => {
// This code must not be reached
expect(true).toEqual(false);
})
.catch(e => {
assert(e instanceof DOMException);
expect(e).toBeInstanceOf(DOMException);
expect(e.name).toEqual('AbortError');
});
waitController.abort();
const end = performance.now();
expect(end - start).toBeLessThanOrEqual(10);
});
test('reject if controller already aborted', async () => {
const start = performance.now();
const waitController = new AbortController();
waitController.abort();
try {
await wait(1000, { signal: waitController.signal });
// This code must not be reached
expect(true).toEqual(false);
} catch (e) {
assert(e instanceof DOMException);
expect(e).toBeInstanceOf(DOMException);
expect(e.name).toEqual('AbortError');
}
waitController.abort();
const end = performance.now();
expect(end - start).toBeLessThanOrEqual(10);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment