How setInterval runs asynchronously - javascript

I have a setInterval function that runs async code that calls the server:
setInterval(()=> {
//run AJAX function here
}, 5000);
If the server doesn't get a response within 5 seconds most probably it will run set Interval again which will then make multiple requests on the same endpoint, is there a way that the setInterval only starts its next 5 second execution after the AJAX function returns a response?

what you want to do is to use setTimeout when ever you get a response
here is some pseudo code
const doAjaxWithDelay = (delay)=>{
setTimeout(()=>{
$.ajax({
...
}).done(()=>{
// do your staff
doAjaxWithDelay(5000)
})
},delay)
}
doAjaxWithDelay(0);

Use setTimeout instead
function myTimer = () => {
setTimeout(()=> {
//run AJAX function here
ajaxFunc();
}, 5000);
function ajaxFunc() {
//case success
//do something
// case failure
// do something
// finally
myTimer();
}
myTimer()

Related

How to run an async function in js with timeouts (for rate limiting)

I'm designing a system where a user will interact with my RESTful API through JS, and will replace the ts html element with a different SVG if the returned answer is true. If the API call returns false, the JS should wait for 5 seconds, before retrying the API call. again, if the API call returns true, the SVG will be changed, and the function will stop calling the API. How can I have the function "sleep" for 5 seconds before running again, and ending the function if the returned API call is true?
Code:
async function getTransaction(){
var lookup = $("meta[name='lookup']").attr("content");
axios.get('http://127.0.0.1:5000/client_api/transaction_status/' + lookup)
.then(function (response) {
var tStat = response.data.transactionStatus;
console
if(tStat){
document.getElementById("ts").innerHTML = 'drawing the new svg and replacing the old one'
console.log('transaction_found')
}
else if(!tStat){
console.log("transaction not found")
}
else{
console.log("error")
}
});
}console.log("hello"); while(true){setTimeout(getTransaction,5000);}
Don't use sleep sice it pauses your programm to pause. Instead use setTimeout like so. This creates an event listener which calls the function again after 5s if tStat is false.
In case of false the function will set an timeout after which the function is called again. After the timeout is completed it clears itself. This step repeats until the api request eventually resolves to true
async function getTransaction() {
var lookup = $("meta[name='lookup']").attr("content");
axios.get('http://127.0.0.1:5000/client_api/transaction_status/' + lookup)
.then(function(response) {
var tStat = response.data.transactionStatus;
console
if (tStat) {
document.getElementById("ts").innerHTML = 'drawing the new svg and replacing the old one'
console.log('transaction_found')
} else {
console.log("transaction not found")
setTimeout(getTransaction, 5000);
}
});
}
console.log("hello");

Wait for setTimeout to complete then proceed to execute rest of the code

function sendMessage(){
...
if(file){
sendingMessage = true;
setTimeout(() => {
sendingMessage = false;
messages = [...messages, chatmessage];
}, 3800)
}
chatmessage = '';
inputRef.focus()
updateScroll();
}
Right now when this function is called, chatmessage is first set to an empty string, etc. then the code in the timeout function is executed which is the corect behaviour. However, is there a way make setTimeout synchronous?
This is the behaviour I want:
If if(file) is true, set sendingMessage = true (sendingMessage triggers a spinning wheel animation)
Wait for 3.8 seconds and execute the content in the timeout function.
Only then, set chatmessage to empty string, etc (rest of the code)
Edit 1:
I can just move the code inside the timeout function but the issue is in my case, if file is not present, it should just skip the timeout function alltogether. Then I would have to write another if block to check if the file is not present to execute the same commands (duplicate code). Another way to solve this would be to put the same code in a function and call it both places but feel like its not the ideal way to go and creating a function to change the value of three variables seems like overkill.
You could make use of a Promise to wait for 3 seconds before executing the code.
For this to work, create a function that returns a promise which resolves after 3 seconds.
function wait(seconds) {
return new Promise(resolve => {
setTimeout(resolve, seconds * 1000);
});
}
Then inside the sendMessage function, call this function, passing in the number of seconds you want to wait. When the promise returned by this wait function resolves, execute the code that you want to execute after wait time is over.
Following code shows an example of how you coulc call wait function inside sendMessage function.
async function sendMessage() {
...
if(file){
sendingMessage = true;
await wait(3); // wait for 3 seconds
sendingMessage = false;
messages = [...messages, chatmessage];
}
chatmessage = '';
inputRef.focus()
updateScroll();
}
You can use promise here, your example is to complex, so I will show smaller
function sleep(time) {
return new Promise(resolve=>setTimeout(resolve, time));
}
async function run() {
console.log(1);
await sleep(1000);
console.log(2);
}
run();
You can't achieve this directly. You have to wrap your timeout function into a promise and await for the result inside an async function.
let file = true
function asyncTimeout(resolver){
return new Promise(resolver)
}
async function sendMessage(){
console.log("Before setTimeout")
if(file){
await asyncTimeout((resolve, reject) => {
setTimeout( function() {
console.log("Timeout finished!")
resolve()
}, 3800)
})
}
console.log("After setTimeout")
}
sendMessage()
Here is a fiddle:
https://jsfiddle.net/38rwznm6/

Avoid Calling a function repeateadly unless its job is finished

I have a function that needs to be called after 5 seconds time interval. This function processes AJAX request in the background (the request goes to other website, so it may take a few seconds). The function is as follows:
function myFunction() {
var sendData = {
cid: cid
};
$.post('xyz.com/somepage.php', sendData, function(response) {
//processes the response
});
setTimeout(myFunction, 5000); //call again after 5 seconds
}
I need to consider a fact that some users may have slow internet connection and the request can take time more than 5 seconds. So, I need to avoid calling that function (or we say avoid sending request) again until its job is finished. I tried the method given in the last paragraph on this link, but it didn't work. Any suggestion? Thanks.
You can call the function on completion of ajax call
function myFunction() {
var sendData = {
cid: cid
};
$.post('xyz.com/somepage.php', sendData, function(response) {
//processes the response
}).done(function() {
setTimeout(myFunction, 5000); //call again after 5 seconds
});
}
Place the setTimeout call within the callback handler:
function myFunction() {
$.post('xyz.com/somepage.php', { cid: cid }, function(response){
//processes the response
setTimeout(myFunction, 5000);//call again after 5 seconds
});
}

How can I perform this JavaScript call after a delay time?

I am pretty new in JavaScript and I have to perform an operation after some time that another previous operation is performed.
So I have this function:
function validaProgetti() {
$.ajax({
type: "POST",
//data: {'checkedRowList' : checkedRowList},
data: JSON.stringify(checkedRowList),
url: "validaProgetti",
contentType:"application/json"
}).done(function(response) {
$('.modal').modal('hide');
sostituisciFrammentoJsp('outputRicerca', response);
//alert("SUCCESS");
}).error(function(xhr) {
alert("ERROR");
manageError(xhr);
});
}
As you can see into the done() body I have these 2 call:
$('.modal').modal('hide');
sostituisciFrammentoJsp('outputRicerca', response);
I need that the sostituisciFrammentoJsp() execution is performed after 3 seconds of delay to ensure that the previoius function is complete.
How can I correctly set a delay for this function?
...after 3 seconds of delay to ensure that the previoius function is complete.
Let's do better than that, and actually wait for the previous function to complete:
$('.modal').modal('hide').one("hidden.bs.modal", function() {
sostituisciFrammentoJsp('outputRicerca', response);
});
(Note I used one, not on, so the handler gets autoremoved after the event occurs.)
Note that I've assumed there you're using a Bootstrap modal, but other "modal" libraries will offer a similar event or callback.
But answering the question you actually asked, you can set up a callback after three seconds with setTimeout:
$('.modal').modal('hide');
setTimeout(function() {
sostituisciFrammentoJsp('outputRicerca', response);
}, 3000);
The number at the end is in milliseconds (thousanths of a second).
Just use javascript setTimeout
setTimeout(function(){
// your code here
}, timeInMillis);
Using this command will schedule an operation for the time you pass.
Option : 1
clearTimeout(window.timer);
window.timer=setTimeout(function(){ // setting the delay for each keypress
ajaxSearchRequest($type); //runs the ajax request
}, 3000);
Option : 2
// set your delay here, 2 seconds as an example...
var my_delay = 2000;
// call your ajax function when the document is ready...
$(function() {
callAjax();
});
// function that processes your ajax calls...
function callAjax() {
$.ajax({
// ajax parameters here...
// ...
success: function() {
setTimeout(callAjax, my_delay);
}
});
}

Javascript: Call function after 10 seconds, then each 1 minute

I have the following scenario:
I have a javascript ajax function loadCars() that needs to be called after the page loads in 10 seconds, and then every 60 seconds.
The below is what I have tried so far:
setTimeout(function(){setInterval(function(){loadCars()}, 60000)}, 10000);
What is happening is that the function is being called after 10 seconds but never again, what am I missing?
You need to call loadCars on setTimeout and on setInterval.
setTimeout(function() {
console.log('first 10 secs');
// loadCars();
setInterval(function() {
console.log('60 secs has passed');
// loadCars();
}, 60000);
}, 10000);
console.log('page loaded');
I don't agree with the answers given because they use setInterval or don't wait for the ajax call to be finished. IMO your should set a new timeout only when the function loadcars (and the ajax call) has finished.
Example:
function loadCars () {
// ajax call happens here
$.ajax()
.then(function(){
// call the function here
setTimeout(function(){
loadCars();
// wait a minute after you recieved the data
}, 60000)
})
}
// wait 10 seconds
setTimeout(function(){
loadCars();
}, 10000)
The advantage if this is that it will only start setting a new timeout when the HTTP request is finished and prevent the function from getting out of sync. If you use setinterval in combination with an ajax call then the next ajax call will happen in 60 seconds even if the current one is delayed for 10 seconds (and you don't want that).
You can call setTimeout(loadCars, 60000) in your loadCars() method that way you call it once initially with setTimeout 10 seconds then from that point it sets a timeout for 1 minute out every time it executes...
function loadCars()
{
//code
setTimeout(loadCars, 60000);
}
setTimeout(loadCars, 10000);
If you want the next timeout to be scheduled only after ajax call is completed then either make a synchronus ajax call or put the setTimeout() in your success callback of your ajax call...The latter being the better option.
To get more control over timings and function calls you could specify them all this way:
function loadCars() {
$('#log').append('Cars loaded<br />');
};
function loadManufacturers() {
$('#log').append('Manufacturers loaded<br />');
};
function loadCustomers() {
$('#log').append('Customers loaded<br />');
};
function loadContent(delays, functions) {
if (functions.length) {
setTimeout(function () {
functions.pop()();
loadContent(delays, functions);
}, delays.pop());
};
};
loadContent([3000, 2000, 1000], [loadCars, loadManufacturers, loadCustomers]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p id="log"></p>
Playground

Categories