Promises: Repeat operation until it succeeds?

前端 未结 6 901
天命终不由人
天命终不由人 2020-11-30 08:28

I want to perform an operation repeatedly, with an increasing timeout between each operation, until it succeeds or a certain amount of time elapses. How do I structure this

6条回答
  •  时光说笑
    2020-11-30 09:23

    Here's an example of how I'd approach this, with some helper functions. Note, the 'maxTimeout' is the more complicated part because you have to race two states.

    // Helper delay function to wait a specific amount of time.
    function delay(time){
        return new Promise(function(resolve){
            setTimeout(resolve, time);
        });
    }
    
    // A function to just keep retrying forever.
    function runFunctionWithRetries(func, initialTimeout, increment){
        return func().catch(function(err){
            return delay(initialTimeout).then(function(){
                return runFunctionWithRetries(
                        func, initialTimeout + increment, increment);
            });
        });
    }
    
    // Helper to retry a function, with incrementing and a max timeout.
    function runFunctionWithRetriesAndMaxTimeout(
            func, initialTimeout, increment, maxTimeout){
    
        var overallTimeout = delay(maxTimeout).then(function(){
            // Reset the function so that it will succeed and no 
            // longer keep retrying.
            func = function(){ return Promise.resolve() };
            throw new Error('Function hit the maximum timeout');
        });
    
        // Keep trying to execute 'func' forever.
        var operation = runFunctionWithRetries(function(){
            return func();
        }, initialTimeout, increment);
    
        // Wait for either the retries to succeed, or the timeout to be hit.
        return Promise.race([operation, overallTimeout]);
    }
    

    Then to use these helpers, you'd do something like this:

    // Your function that creates a promise for your task.
    function doSomething(){
        return new Promise(...);
    }
    
    runFunctionWithRetriesAndMaxTimeout(function(){
        return doSomething();
    }, 1000 /* start at 1s per try */, 500 /* inc by .5s */, 30000 /* max 30s */);
    

提交回复
热议问题