You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			134 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			134 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			TypeScript
		
	
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>,
 | 
						|
  timeoutMs: number = 2000
 | 
						|
): Promise<T> {
 | 
						|
  const timeoutPromise = new Promise<T>((_, rej) => {
 | 
						|
    const wait = setTimeout(() => {
 | 
						|
      clearTimeout(wait);
 | 
						|
      rej(new Error('Task timed out.'));
 | 
						|
    }, timeoutMs);
 | 
						|
  });
 | 
						|
 | 
						|
  const taskPromise = new Promise(async (res, rej) => {
 | 
						|
    try {
 | 
						|
      await toPromise(task(res));
 | 
						|
    } catch (e) {
 | 
						|
      rej(e);
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  return Promise.race([timeoutPromise, taskPromise]) as Promise<T>;
 | 
						|
}
 | 
						|
 | 
						|
export interface PollOptions {
 | 
						|
  timeoutMs: 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 task The task 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 = {
 | 
						|
    timeoutMs: 2000,
 | 
						|
    interval: 100,
 | 
						|
  };
 | 
						|
 | 
						|
  const { timeoutMs, interval } = {
 | 
						|
    ...defaults,
 | 
						|
    ...options,
 | 
						|
  };
 | 
						|
 | 
						|
  const endTime = Date.now() + timeoutMs;
 | 
						|
  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>,
 | 
						|
  timeoutMs: number = 2000
 | 
						|
) {
 | 
						|
  // This is causing unhandled promise rejection somewhere in MessageQueue tests
 | 
						|
  return poll(
 | 
						|
    async done => {
 | 
						|
      const result = await toPromise(check());
 | 
						|
      if (result) {
 | 
						|
        done();
 | 
						|
      }
 | 
						|
    },
 | 
						|
    {
 | 
						|
      timeoutMs,
 | 
						|
      interval: timeoutMs / 20,
 | 
						|
    }
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
export async function timeout<T>(
 | 
						|
  promise: Promise<T>,
 | 
						|
  timeoutMs: number = 2000
 | 
						|
): Promise<T> {
 | 
						|
  const timeoutPromise = new Promise<T>((_, rej) => {
 | 
						|
    const wait = setTimeout(() => {
 | 
						|
      clearTimeout(wait);
 | 
						|
      rej(new Error('Task timed out.'));
 | 
						|
    }, timeoutMs);
 | 
						|
  });
 | 
						|
 | 
						|
  return Promise.race([timeoutPromise, promise]);
 | 
						|
}
 |