NodeJS Timeout a Promise if failed to complete in time

前端 未结 7 562
忘掉有多难
忘掉有多难 2020-11-27 04:07

How can I timeout a promise after certain amount of time? I know Q has a promise timeout, but I\'m using native NodeJS promises and they don\'t have .timeout function.

7条回答
  •  盖世英雄少女心
    2020-11-27 04:31

    A wrapper would be convenient in this situation

    usage

    const result = await withTimeout(() => doSomethingAsync(...args), 3000)();
    

    or

    const result = await withTimeout(doSomethingAsync, 3000)(...args);
    

    or even

    const doSomethingAsyncWithTimeout = withTimeout(doSomethingAsync, 3000);
    const result = await doSomethingAsyncWithTimeout(...args);
    

    implementation

    /**
     * returns a new function which calls the input function and "races" the result against a promise that throws an error on timeout.
     *
     * the result is:
     * - if your async fn takes longer than timeout ms, then an error will be thrown
     * - if your async fn executes faster than timeout ms, you'll get the normal response of the fn
     *
     * ### usage
     * ```ts
     * const result = await withTimeout(() => doSomethingAsync(...args), 3000);
     * ```
     * or
     * ```ts
     * const result = await withTimeout(doSomethingAsync, 3000)(...args);
     * ```
     * or even
     * ```ts
     * const doSomethingAsyncWithTimeout = withTimeout(doSomethingAsync, 3000);
     * const result = await doSomethingAsyncWithTimeout(...args);
     * ```
     */
    const withTimeout =  Promise>(logic: T, ms: number) => {
      return (...args: Parameters) => {
        // create a promise that rejects in  milliseconds; https://italonascimento.github.io/applying-a-timeout-to-your-promises/
        const timeout = new Promise((resolve, reject) => {
          const id = setTimeout(() => {
            clearTimeout(id);
            reject(new Error(`promise was timed out in ${ms} ms, by withTimeout`));
          }, ms); // tslint:disable-line align
        });
    
        // returns a "race" between our timeout and the function executed with the input params
        return Promise.race([
          logic(...args), // the wrapped fn, executed w/ the input params
          timeout, // the timeout
        ]) as Promise;
      };
    };
    
    

提交回复
热议问题