Reputation: 397
I need to send an ajax request with an interval of 5s
const asyncF = async () => { await /* some ajax stuff */ }
asyncF(); // fire off an ajax request first
setInterval(() => { // start an interval
asyncF();
}, 5 * 1000);
Normally the asyncF
should succeed within 5s, so 5s between sucessive starts are normally ok and simple, but I want to make sure when next asyncF fires, the previous one has succeeded. If the previous one didn't succeed, then start a new interval whenever previous one succeeds
asyncF
takes less than 5s to succeed, all is good!asyncF
takes more than 5s to succeed, I need to clear the interval and start a new interval whenever asyncF
succeedsasyncF
fails within 5s, I also need to immediately call it again and set a new intervalI came up with this naive idea which kind of solves the problem
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;
}
However with this method, if asyncF
takes more than 5s to succeed, the timer start counting before asyncF
succeeds
Is there any mature and graceful solution to solve the problem?
Upvotes: 0
Views: 632
Reputation: 136154
It is easier to do this not with a setInterval
and have to work out when to cancel/restart it, but with a setTimeout
.
The idea is that you set a timer for 5 seconds, and if the previous function has finished you recall the function. If the timeout has been reached while the function is executing you execute it immediately, and same goes for if an error occurs.
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();
}
}
In the example below I have mocked out your asyncF
function whereby it randomly suceeds or fails (80% chance of success) and has a random delay which sometimes goes over 5 seconds. However this is no different from your ajax-based async function. It would work exactly the same way!
You should see that
Hopefully this matches your requirements
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()
Upvotes: 1