重试Javascript.Promise.reject有限次数或直到成功

问题描述:

我有一个函数说myMainFunction,从客户端调用,这又调用mypromisified函数。重试Javascript.Promise.reject有限次数或直到成功

场景: mypromisified功能可以间歇性地失败,我需要调用一个延迟此功能(以指数增长),直到成功,或者直到最大没有达到的尝试。

我有什么到目前为止

下面的代码说明了我的情况,并重复自己,直到成功,但直到达到一定的数量就无限期地而不是试图

// called once from the client 
 
myMainFuntion(); 
 

 
function rejectDelay(delay, reason) { 
 
    // call main function at a delayed interval until success 
 
    // but would want to call this only a limited no of times 
 
    setTimeout(() => { 
 
     myMainFuntion(); // calling main function again here but with a delay 
 
    }, delay); 
 
} 
 

 

 
function myMainFuntion() { 
 
    var delay = 100; 
 
    var tries = 3; 
 
    tryAsync().catch(rejectDelay.bind(null, delay)); 
 
} 
 

 
function tryAsync() { 
 
    return new Promise(function(resolve, reject) { 
 
    var rand = Math.random(); 
 
    console.log(rand); 
 
    if (rand < 0.8) { 
 
     reject(rand); 
 
    } else { 
 
     resolve(); 
 
    } 
 
    }); 
 

 
}

while循环里面的rejectDelay肯定不会工作,因为计数器会在setInterval内部的实际函数执行之前增加,所以我不确定如何去做这件事?所以......

我试图promisifyingsetInterval像这样明知会失败:(因为它不递减计数器,但不知道如何得到它的权利无论是。

function rejectDelay(delay, maximumTries, reason) { 
 
    return new Promise(function (resolve, reject) { 
 
    console.log(tries + ' remaining'); 
 
    if (--maximumTries > 0) { 
 
     setTimeout(function() { 
 
     foo(); 
 
     }, 500); 
 
    } 
 
    }); 
 
} 
 
function myMainFunction() { 
 
    var delay = 100; 
 
    var maximumTries = 3; 
 
    tryAsync().catch(rejectDelay.bind(null, delay, maximumTries)); 
 
}

+0

相关的答案:[无极重试设计模式](http://*.com/questions/38213668/promise-retry-design-patterns/38214203#38214203)和[重试一个承诺步骤]( http://*.com/questions/37993365/retry-a-promise-step/37995874#37995874) – jfriend00

使用几个辅助函数,我用了很多,这个就变得非常容易

的“帮手”

Promise.wait = (time) => new Promise(resolve => setTimeout(resolve, time || 0)); 
Promise.retry = (cont, fn, delay) => fn().catch(err => cont > 0 ? Promise.wait(delay).then(() => Promise.retry(cont - 1, fn, delay)) : Promise.reject('failed')); 

的代码:

function myMainFuntion() { 
     var delay = 100; 
     var tries = 3; 
     Promise.retry(tries, tryAsync, delay); 
} 

ES5版本的助手

Promise.wait = function (time) { 
    return new Promise(function (resolve) { 
     return setTimeout(resolve, time || 0); 
    }); 
}; 
Promise.retry = function (cont, fn, delay) { 
    return fn().catch(function (err) { 
     return cont > 0 ? Promise.wait(delay).then(function() { 
      return Promise.retry(cont - 1, fn, delay); 
     }) : Promise.reject('failed'); 
    }); 
}; 
+0

谢谢你一个简洁的解决方案:)。我明白'retry'上的递归调用,但无法让我的头绕过等待函数 - >我看到你正在返回一个新的Promise,但不能解析或拒绝相同的答案吗? - 在我的脑海里意味着'.then'上的'Promise.wait()'永远不会被调用?你介意多给我解释一下吗?提前谢谢 PS:我知道它是从撕裂工作:),我在这里https:// jsfiddle。net/jayas_godblessall/j50u8br9/- 但如上所述 - 不在我的脑海里工作:( – Jaya

+1

“setTimeout”的第一个参数是一个函数来运行...它设置为'resolve'...因此解析在时间后被调用'ms –

+0

ahh!gotcha!thank you! – Jaya

稍微不同的方法,它使用 “异步递归” 的调用函数中的嵌套函数退货承诺:

function retry(func, maxTries, delay) { 
 
    var reTry = 0; 
 
    return new Promise(function(resolve, reject) { 
 
     function callFunc() { 
 
      try 
 
      { 
 
       func().then(resolve, function(reason) { 
 
        if(++reTry >= maxTries) { 
 
         reject(reason); 
 
        } 
 
        else { 
 
         setTimeout(callFunc, 
 
         typeof delay=="function" ? delay(retry) : delay); 
 
        } 
 
       }); 
 
      } 
 
      catch(e) { 
 
       reject(e); 
 
      } 
 
     } 
 
     callFunc();  
 
    }); 
 
} 
 

 
// ******* run snippet to test ******** 
 

 

 
var retryCount = 0; 
 
function getDelay(n) { 
 
// return 100 * n*n + 500; // for example 
 
     ++ retryCount; 
 
     return 100; // for testing 
 

 
} 
 

 
function testFunc() { 
 
    return Math.random() < 0.8 ? Promise.reject("too many tries") : Promise.resolve("success"); 
 
} 
 

 
retry(testFunc, 5, getDelay).then(
 
function(data) { console.log("data: %s, retryCount %s", data, retryCount);}, 
 
function(reason){console.log("reason: %s, retryCount %s", reason, retryCount);} 
 
)