Reputation: 85
I want to execute the code inside setInterval in an order it comes.
In real-time I am fetching data from different endpoints and I want to execute the code in the sequence it calls. response Time for some fetch request might be more so I want it to wait for the next call(fetch request) till the current request does not complete.
const s = 100;
/* Request number */
let seqN = 0;
const request = requestNumber =>
// Request will be done from 1 to 5 seconds
setTimeout(() => {
out(`Refresh request number ${requestNumber} is done`);
}, requestResponseTime(1, 6) * s);
setInterval(() => {
request(seqN++);
}, 1 * s);
/**
* Response time could take more than
* interval time
*/
function requestResponseTime(min, max) {
return Math.random() * (max - min) + min;
}
// Debug printing
out("Applicaiton started");
function out(message) {
console.log(`${new Date().toUTCString()}: ${message}`);
}
Upvotes: 0
Views: 176
Reputation: 85
I am able to achieve the functionality using recursion rather than the setInterval. I have given css code for this too so we can view the working properly.
import "./styles.css";
const s = 1000;
/* Request number */
let seqN = 0;
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
function myData() {
request(seqN++)
.then(data => {
out(data);
delay(1 * s);
myData();
})
.catch(err => {
console.log("err", err);
seqN--;
myData();
// out(err);
});
}
myData();
// Failed request simulation
// DON'T CHANGE THE CODE AFTER
function request(requestNumber) {
return new Promise((resolve, reject) => {
const isOK = Math.random() >= 0.5;
setTimeout(
() =>
isOK
? resolve(`${requestNumber} is <strong>OK</strong>`)
: reject(`${requestNumber} is <span>KO</span>`),
requestResponseTime(1, 6) * s
);
});
}
/**
* Response time could take more than
* interval time
*/
function requestResponseTime(min, max) {
return Math.random() * (max - min) + min;
}
// Debug printing
out("Applicaiton started");
function out(message) {
// console.log(`${new Date().toUTCString()}: ${message}`);
document.getElementById(
"app"
).innerHTML += `<pre>${new Date().toUTCString()}: ${message}</pre>`;
}
body {
font-family: sans-serif;
}
strong {
color: green;
}
span {
color: red;
}
Upvotes: 0
Reputation: 485
well there are two ways first is that you make the first call and wait for response then you make the second call, the other is that you make all the calls first but you do your operation on them on the order they were called. I am guessing you are looking for the second one, so if they are all fetch calls you can do it like this:
function async sequentialCalls() {
const firstCall = fetch(first);
const secondCall = fetch(second);
const thirdCall = fetch(third);
const firstRespone = await firstCall
....operation on firstResponse
const secondRespone = await secondCall
....operation on secondResponse
const thirdRespone = await thirdCall
....operation on thirdResponse
}
as for the setTimeout I think you need to promisify the response to be able to use it with await
Upvotes: 0
Reputation: 73
If I get your question well, you want to only execute a new request after the previous one has been completed?
OR
You are worried about setInterval being fired even when the previous one request hasn't been completed?
If yes, then you need to have a checker/flag that would check if the previous request has been completed or not.
A quick example would be:
var isLoading = false;
setInterval(() => {
if(isLoading === true) return; // more like do nothing
else {
isLoading = true;
// call your request function here
}
}, 1 * s)
Ensure not to put the checker/flag inside your setInterval/setTimeout call. make it a global variable as you did for your seqN. This way it's content would only change when something actually happens.
Also, ensure to set isLoading to false inside your request function as soon as your request function is done processing.
Upvotes: 1