NodeJS Timeout a Promise if failed to complete in time

前端 未结 7 557
忘掉有多难
忘掉有多难 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:21

    While maybe there's no support for a promise timeout, you could race promises:

    var race = Promise.race([
      new Promise(function(resolve){
        setTimeout(function() { resolve('I did it'); }, 1000);
      }),
      new Promise(function(resolve, reject){
        setTimeout(function() { reject('Timed out'); }, 800);
      })
    ]);
    
    race.then(function(data){
      console.log(data);
      }).catch(function(e){
      console.log(e);
      });

    A generic Promise.timeout:

    Promise.timeout = function(timeout, cb){
      return Promise.race([
      new Promise(cb),
      new Promise(function(resolve, reject){
        setTimeout(function() { reject('Timed out'); }, timeout);
      })
    ]);
    }
    

    Example:

        Promise.timeout = function(timeout, cb) {
          return Promise.race([
            new Promise(cb),
            new Promise(function(resolve, reject) {
              setTimeout(function() {
                reject('Timed out');
              }, timeout);
            })
          ]);
        }
        
        function delayedHello(cb){
          setTimeout(function(){
            cb('Hello');
            }, 1000);
          }
        
        Promise.timeout(800, delayedHello).then(function(data){
          console.log(data);
          }).catch(function(e){
          console.log(e);
          }); //delayedHello doesn't make it.
    
        Promise.timeout(1200, delayedHello).then(function(data){
          console.log(data);
          }).catch(function(e){
          console.log(e);
          }); //delayedHello makes it.

    Might be a little bit costly, because you are actually creating 3 promises instead of 2. I think it's clearer this way though.

    You might want to setup a promise instead of having the function construct it for you. This way you separate concerns and you are ultimately focused on racing your promise against a newly built promise that will reject at x miliseconds.

    Promise.timeout = function(timeout, promise){
      return Promise.race([
      promise,
      new Promise(function(resolve, reject){
        setTimeout(function() { reject('Timed out'); }, timeout);
      })
    ]);
    }
    

    How to use:

    var p = new Promise(function(resolve, reject){
        setTimeout(function() { resolve('Hello'); }, 1000);
    });
    
    Promise.timeout(800, p); //will be rejected, as the promise takes at least 1 sec.
    

提交回复
热议问题