'Fetch call every 2 seconds, but don't want requests to stack up
I am trying to make an API call and I want it to repeat every 2 seconds. However I am afraid that if the system doesn't get a request back in 2 seconds, that it will build up requests and keep trying to send them. How can I prevent this?
Here is the action I am trying to fetch:
const getMachineAction = async () => {
try {
const response = await fetch( 'https://localhost:55620/api/machine/');
if (response.status === 200) {
console.log("Machine successfully found.");
const myJson = await response.json(); //extract JSON from the http response
console.log(myJson);
} else {
console.log("not a 200");
}
} catch (err) {
// catches errors both in fetch and response.json
console.log(err);
}
};
And then I call it with a setInterval.
function ping() {
setInterval(
getMachineAction(),
2000
);
}
I have thought of doing some promise like structure in the setInterval to make sure that the fetch had worked and completed, but couldn't get it working.
Solution 1:[1]
The Promise.all() Solution
This solution ensures that you don't miss-out on 2 sec delay requirement AND also don't fire a call when another network call is underway.
function callme(){
//This promise will resolve when the network call succeeds
//Feel free to make a REST fetch using promises and assign it to networkPromise
var networkPromise = fetch('https://jsonplaceholder.typicode.com/todos/1');
//This promise will resolve when 2 seconds have passed
var timeOutPromise = new Promise(function(resolve, reject) {
// 2 Second delay
setTimeout(resolve, 2000, 'Timeout Done');
});
Promise.all(
[networkPromise, timeOutPromise]).then(function(values) {
console.log("Atleast 2 secs + TTL (Network/server)");
//Repeat
callme();
});
}
callme();
Note: This takes care of the bad case definition as requested by the author of the question:
"the "bad case" (i.e. it takes longer than 2 seconds) is I want it to skip that request, and then send a single new one. So at 0 seconds the request sends. It takes 3 seconds to execute, then 2 seconds later (at 5) it should reexcute. So it just extends the time until it sends."
Solution 2:[2]
You could add a finally to your try/catch with a setTimeout instead of using your setInterval.
Note that long polling like this creates lot more server load than using websockets which themselves are a lot more real time
const getMachineAction = async () => {
try {
const response = await fetch( 'https://localhost:55620/api/machine/');
if (response.status === 200) {
console.log("Machine successfully found.");
const myJson = await response.json(); //extract JSON from the http response
console.log(myJson);
} else {
console.log("not a 200");
}
} catch (err) {
// catches errors both in fetch and response.json
console.log(err);
} finally {
// do it again in 2 seconds
setTimeout(getMachineAction , 2000);
}
};
getMachineAction()
Solution 3:[3]
Simple! Just store whether it's currently making a request, and store whether the timer has tripped without sending a new request.
let in_progress = false;
let missed_request = false;
const getMachineAction = async () => {
if (in_progress) {
missed_request = true;
return;
}
in_progress = true;
try {
const response = await fetch('https://localhost:55620/api/machine/');
if (missed_request) {
missed_request = false;
setTimeout(getMachineAction, 0);
}
if (response.status === 200) {
console.log("Machine successfully found.");
const myJson = await response.json(); //extract JSON from the http response
console.log(myJson);
} else {
console.log("not a 200");
}
} catch (err) {
// catches errors both in fetch and response.json
console.log(err);
} finally {
in_progress = false;
}
};
To start the interval, you need to omit the ():
setInterval(getMachineAction, 2000);
Solution 4:[4]
you can try this, which i get the exact result i was looking for
const getMachineAction = async () => {
try {
const response = await fetch( 'https://localhost:55620/api/machine/');
if (response.status === 200) {
console.log("Machine successfully found.");
const myJson = await response.json(); //extract JSON from the http response
console.log(myJson);
} else {
console.log("not a 200");
}
} catch (err) {
// catches errors both in fetch and response.json
console.log(err);
} finally {
// do it again in 2 seconds
setTimeout(getMachineAction , 2000);
}
};
getMachineAction()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | |
| Solution 4 | madsadi |
