基于ajax结果或承诺状态的setInterval



我需要发送一个间隔为5s的ajax请求

const asyncF = async () => { await /* some ajax stuff */ }
asyncF(); // fire off an ajax request first
setInterval(() => { // start an interval
asyncF();
}, 5 * 1000);

通常asyncF应该在5秒内成功,所以连续启动之间的5秒通常是ok和简单的,但我想确保当下一个asyncF触发时,前一个已经成功。如果前一个没有成功,那么每当前一个成功时,就开始一个新的间隔

  • 如果asyncF的成功时间小于5s,则一切正常!
  • 如果asyncF超过5s才成功,我需要清除间隔,当asyncF成功时开始一个新的间隔
  • 如果asyncF在5s内失败,我也需要立即再次调用它并设置一个新的间隔

我想出了这个解决问题的幼稚想法

let flag = true; // global variable flag
const asyncF = async () => {
await /* some ajax stuff */
flag = true;
}
try {
asyncF();
setTimer();
} catch {
asyncF();
setTimer();
}
function setTimer() {
let timer = setInterval(() => {
if (flag) {
asyncF();
} else {
clearInterval(timer);
timer = setTimer();
}
}, 5 * 1000);
return timer;
}

然而,使用这种方法,如果asyncF超过5s才成功,计时器在asyncF成功之前开始计数

有没有成熟优雅的解决方案?

不使用setInterval更容易做到这一点,并且必须计算出何时取消/重新启动它,但使用setTimeout

这个想法是你设置了一个5秒的计时器,如果前一个函数已经完成,你就重新调用这个函数。如果在函数执行时超时,则立即执行它,如果发生错误也一样。

async function limitedFunction(){
let isRunning = true;
let timeoutReached = false;
setTimeout( () => {
timeoutReached = true;
if(!isRunning)
limitedFunction();
},5000);

try{
await asyncF();
isRunning = false;
if(timeoutReached)
limitedFunction();
} 
catch {
limitedFunction();
}  
}

在下面的例子中,我模拟了你的asyncF函数,它随机成功或失败(80%的成功机会),并有一个随机延迟,有时超过5秒。但是,这与基于ajax的异步函数没有什么不同。它会以完全相同的方式工作!

你应该看到

  • 当函数在<5s内成功时,它等待5s,因为原始启动再次启动
  • 当函数在>5s内成功时,它立即重新启动
  • 当函数失败时,立即重新启动。

希望这符合您的要求

async function asyncF(){

const delay = (ms) => new Promise(resolve => setTimeout(resolve,ms))

const rndFunc = Math.random();
const rndTime = Math.floor((Math.random() * 7) + 1);

if(rndFunc < 0.8){
console.log(`asyncF will succeed in ${rndTime}s`)
await delay(rndTime*1000)
}
else{
console.log(`asyncF will fail in ${rndTime}s`);
await delay(rndTime*1000)
throw "I failed"
}  
}
async function limitedFunction(){
let isRunning = true;
let timeoutReached = false;
setTimeout( () => {
timeoutReached = true;
if(!isRunning)
limitedFunction();
},5000);

try{
await asyncF();
isRunning = false;
if(timeoutReached)
limitedFunction();
} 
catch {
limitedFunction();
}  
}
limitedFunction()

最新更新