Modify periodic check implementation
parent
d862269f8d
commit
3bf5796cd5
@ -0,0 +1,118 @@
|
||||
type SimpleFunction<T> = (arg: T) => void;
|
||||
type Return<T> = Promise<T> | T;
|
||||
|
||||
async function toPromise<T>(value: Return<T>): Promise<T> {
|
||||
return value instanceof Promise ? value : Promise.resolve(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a promise which waits until `done` is called or until `timeout` period is reached.
|
||||
* If `timeout` is reached then this will throw an Error.
|
||||
*
|
||||
* @param task The task to wait for.
|
||||
* @param timeout The timeout period.
|
||||
*/
|
||||
export async function waitForTask<T>(
|
||||
task: (done: SimpleFunction<T>) => Return<void>,
|
||||
timeout: number = 2000
|
||||
): Promise<T> {
|
||||
const timeoutPromise = new Promise<T>((_, rej) => {
|
||||
const wait = setTimeout(() => {
|
||||
clearTimeout(wait);
|
||||
rej(new Error('Task timed out.'));
|
||||
}, timeout);
|
||||
});
|
||||
|
||||
const taskPromise = new Promise(async (res, rej) => {
|
||||
try {
|
||||
await toPromise(task(res));
|
||||
} catch (e) {
|
||||
rej(e);
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.race([timeoutPromise, taskPromise]) as Promise<T>;
|
||||
}
|
||||
|
||||
interface PollOptions {
|
||||
timeout: number;
|
||||
interval: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a promise which calls the `task` every `interval` until `done` is called or until `timeout` period is reached.
|
||||
* If `timeout` is reached then this will throw an Error.
|
||||
*
|
||||
* @param check The check which runs every `interval` ms.
|
||||
* @param options The polling options.
|
||||
*/
|
||||
export async function poll(
|
||||
task: (done: SimpleFunction<void>) => Return<void>,
|
||||
options: Partial<PollOptions> = {}
|
||||
): Promise<void> {
|
||||
const defaults: PollOptions = {
|
||||
timeout: 2000,
|
||||
interval: 1000,
|
||||
};
|
||||
|
||||
const { timeout, interval } = {
|
||||
...defaults,
|
||||
...options,
|
||||
};
|
||||
|
||||
const endTime = Date.now() + timeout;
|
||||
let stop = false;
|
||||
const finish = () => {
|
||||
stop = true;
|
||||
};
|
||||
|
||||
const _poll = async (resolve: any, reject: any) => {
|
||||
if (stop) {
|
||||
resolve();
|
||||
} else if (Date.now() >= endTime) {
|
||||
finish();
|
||||
reject(new Error('Periodic check timeout'));
|
||||
} else {
|
||||
try {
|
||||
await toPromise(task(finish));
|
||||
} catch (e) {
|
||||
finish();
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
void _poll(resolve, reject);
|
||||
}, interval);
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
void _poll(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a promise which waits until `check` returns `true` or rejects if `timeout` preiod is reached.
|
||||
* If `timeout` is reached then this will throw an Error.
|
||||
*
|
||||
* @param check The boolean check.
|
||||
* @param timeout The time before an error is thrown.
|
||||
*/
|
||||
export async function waitUntil(
|
||||
check: () => Return<boolean>,
|
||||
timeout: number = 2000
|
||||
) {
|
||||
// This is causing unhandled promise rejection somewhere in MessageQueue tests
|
||||
return poll(
|
||||
async done => {
|
||||
const result = await toPromise(check());
|
||||
if (result) {
|
||||
done();
|
||||
}
|
||||
},
|
||||
{
|
||||
timeout,
|
||||
}
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue