usage of setTimeout function in AJAX - javascript

I.m currently following a tutorial about how to load content from a MYSQL db without reloading the page.
I just want to understand the use of setTimeout in this code. What's it for? I tried removing that part and ajax still works. Why would you need to delay a task, isn't ajax meant to be realtime update?
$(document).ready(function () {
done();
});
function done() {
setTimeout(function () {
updates();
done();
}, 200);
}
function updates() {
$.getJSON("update.php", function (data) {
$("ul").empty();
$.each(data.result, function () {
$("ul").append("<li>ID: " + this['msg_id'] + "</li><br /><li>ID: " + this['msg'] + "</li><br />");
});
});
}

In that code, the setTimeout is being used to get updates from the server 5 times a second (which is probably too frequently). Without it, it only get the updates once (if updates() is ever called).

The setTimeout appears in the done() function, and when the setTimeout executes (after 200ms) it calls itself recursively. Thus the updates() function will be called every 200ms for the life of the page.
If update.php is some kind of message stream, then this code requires the setTimeout to continuously poll for new messages and append them to a list.

settimeout and setTimeout
In your code setTimeout calls done function and updates() function after every 200 millisecond
function done() {
setTimeout(function () {
updates();
done();
}, 200);
}
like you if you remove setTimeout it still works
function done() {
updates();
done();
}
as it creates infinite loop of done function
but no delay which was caused by setTimeout

It's being used to delay recursion by 200 ms. If you remove the timeout, the loop will work just the same, but you'll probably run out of memory before too long.
A more interesting/instructive take on this example would be to pass done to updates as a callback and call it on success.

The function setTimeout takes a function and a number as parameter, it executes the function after the given number of milliseconds.
In your code it means: the function updates() is called every 200 milliseconds - 5 times a second.
Read more about it here:
https://developer.mozilla.org/en/docs/Web/API/window.setTimeout

Your code uses setTimeout to poll regardless of the resource returning a result.
This version will only re-execute in case of success.
Of course if you want your code to poll always, regardless so it can recover from an error at the server, you should not change. But 200 MS is in any case far too often
$(function () {
updates();
});
function updates() {
$.getJSON("update.php", function (data) {
$("ul").empty();
$.each(data.result, function () {
$("ul").append("<li>ID: " + this['msg_id'] + "</li>"+
"<li> " + this['msg'] + "</li>");
});
setTimeout(updates, 10000); // do it again in 10 seconds
});
}

Related

Why can't I my function to be called every few seconds?

I am trying to call a function every few seconds as shown here:
HTML:
<div id="Result">Click here for the message.</div>
JS:
$(document).ready(function () {
$("#Result").click(function () {
var timeout = setTimeout(function () {
$('post').each(function () {
dater();
});
}, 3000);
});
});
function dater() {
$("#Result").text("hi");
}
The problem is that this is not being triggered; so, what am I missing, or doing wrong?
Alternatively, is there a better way to do what I am trying to do?
Problem #1
You did not include jQuery in the JS Fiddle demo.
Problem #2
A setTimeout only executes once, unless it calls itself. Either do that or use setInterval, which executes every x milliseconds.
Also, there are no <post> elements in HTML, use a class instead. Also include it in the fiddle or it won't work.
$(document).ready(function () {
$("#Result").click(function () {
var timeout = setInterval(function () {
$('.post').each(dater);
}, 3000);
});
});
function dater() {
$("#Result").text("hi");
}
JS Fiddle Demo
Note
Both setTimeout and setInterval only start after the time set. If you want the function to be executed instantly as well, you could do something like this.
Let's go further
It might be a better choice to use setTimeout, as mentioned in other answers. Here is an example on how to do that:
var timeout;
$(document).ready(function () {
$("#Result").click(daterForEachPost);
});
function daterForEachPost() {
$('.post').each(dater);
// The function will call itself every 3000 ms
timeout = setTimeout(daterForEachPost, 3000);
}
function dater() {
$("#Result").text("hi");
}
JS Fiddle Demo
The .setTimeout() method will run only once. In order to run periodically (with the specified timeout interval), use .setInterval().
Try to use setInterval() instead.
Here the information provided in w3schools.
"The setInterval() method will wait a specified number of milliseconds, and then execute a specified function, and it will continue to execute the function, once at every given time-interval."

What is the correct way to do an infinite loop that calls a method in Jquery or Javascript?

I have a page that I want to update non stop, every few seconds.
For this, I wrote the following:
var to;
$(function () {
to = setTimeout(updateDivContent, 2000);
});
function updateDivContent() {
$('#topbox').load('/home/blabla', null);
$('#leftgraph').load('/home/blabla', null, function () {
to = setTimeout(updateDivContent, 2000);
});
};
This worked, however, it leads to what I presume is a memory leak as after around 15 minutes, the computer almost freezes up with the browser taking up all available memory and CPU.
I am guessing that the Timeout is basically stacking, but, I am not sure how to fix this. I have tried getting rid of the second timeout and putting the first one inside a while(true) loop, but, I just couldn't get it to work.
Can anyone suggest anything?
This looks fine actually. But if the first Ajax call does not finish within two seconds, it will stack, and this could (don't know for sure) cause problems.
The timeout itself does not stack, since you are initiating a new one only after the previous one finished.
Try to initiate a new timeout once both Ajax requests finished:
$.when($('#topbox').load('/home/blabla'),
$('#leftgraph').load('/home/blabla')
).then(function () {
setTimeout(updateDivContent, 2000);
});
Reference: $.when
I think it is better to use setInterval instead of setTimeOut.
See this post.
You probably want to call clearTimeout to invalidate the previous timer, like this:
clearTimeout(to);
to = setTimeout(updateDivContent, 2000);
can you this it will call ever 2 second
to = setInterval("updateDivContent", 2000);
function updateDivContent() {
$('#topbox').load('/home/blabla', null);
$('#leftgraph').load('/home/blabla', null, function () {
//to = setTimeout(updateDivContent, 2000);
});
};
Try setInterval:
var to;
$(function () {
to = setInterval(updateDivContent, 2000);
});
function updateDivContent() {
$('#topbox').load('/home/blabla', null);
$('#leftgraph').load('/home/blabla')
};

How to create a pause in javascript/jquery code that follows a call to asynchronous function

How can I call an asynchronous function and then create a pause in the code that follows the call to the function so that I may be (almost) sure that the asynchronos function has finished?
I don't want to put the code that follows the call inside a function and then delay it to achieve this, just pause the code as it is for a few seconds.
Here is what I mean:
<script>
asynchronousFunction(); // start running immediatly
waitFor10Seconds(); // only the following code should wait while the async
// function is running in the background
rest of the code; // this code will start running after 10 seconds have passed
// since the async function has been called
</script>
It's called setTimeout
asyncThing();
setTimeout(function() {
// do stuff
}, 10000);
Ideally though the async operation should allow you to pass a callback so you turn it into
asyncThing(function() {
// do stuff
});
As mentioned, you should really use a callback. It's easy with jQuery:
$.get("page.php", "key1=value1", function(data) {
// Code in here will be executed when response has been received
});
http://api.jquery.com/jQuery.get/
You can of course use $.post() if you'd rather POST the data.
Aldo a callback is better practice, this what you asked for
window.setTimeout(function(){ ... }, 10000);

setInterval in jQuery happens too fast

I use setInterval and sometimes it happens "too fast". Here how it looks:
setInterval(function() {
//here comes ajax functions and so on.
}, 1000);
Sometimes setInterval happens faster than all those ajax functions and it gives me two messages instead of one. What a solution to this?
It's hard to tell what you're running into, the question is a bit unclear.
setInterval is great for some things, but not for anything where you're going to be mixing other asynchronous stuff in with it. Instead, use the "rescheduling setTimeout" idiom:
setTimeout(doSomething, 1000);
function doSomething() {
$.ajax("your_url", {
success: function() {
// Do something here
// Do something else here
},
complete: function() {
// Previous run complete, schedule the next run
setTimeout(doSomething, 1000);
}
});
}
...because, after all, your ajax call may take more than a second to complete.
If that's not the problem you're having, my guess is your code looks something like this:
setInterval(function() {
$.ajax("your_url", {
success: function() {
// Do something here
}
});
// Do something else here
}, 1000);
...and you're wondering why the "Do something else here" code is running before the "Do something here" code. If so, the reason is that by default, ajax calls are asynchronous. Your call to $.ajax starts the call, but that's all; then all your other code runs before the success (or error) callbacks occur.
The fix, of course, is to not do anything else at the top level that relies on the success callback:
setInterval(function() {
$.ajax("your_url", {
success: function() {
// Do something here
// Do something else here
}
});
}, 1000);
With jQuery 1.5.x you can use the Then() for deferred object. This is a nice way to say once you are done then() do this. You can also use the When() option to have it wait for more than one ajax request to complete.
These two things are very cool and powerful.
http://api.jquery.com/deferred.then/
http://api.jquery.com/jQuery.when/
Set a flag that indicates that the ajax fetches are in process. When all of the ajax fetches complete, clear the flag. At the top of your setInterval function, return immediately if the flag is set.
It's better not to use setInterval, but to set a fresh setTimeout each time. For example:
setTimeout(function ajaxStuff() {
// here comes ajax functions and so on.
setTimeout(ajaxStuff, 1000);
}, 1000);
Of course, if the functions within are asynchronous, as AJAX requests normally are, the setTimeout call will still come too soon. You'll need to write some code that calls setTimeout when the requests are complete. $.when helps you with this, since $.ajax and other jQuery AJAX methods implement $.Deferred:
setTimeout(function ajaxStuff() {
$.when(
$.ajax({
url: 'ajax1.htm'
}),
$.ajax({
url: 'ajax2.htm'
}),
$.ajax({
url: 'ajax3.htm'
})
).done(function() {
setTimeout(ajaxStuff, 1000);
});
}, 1000);
I think the problem here is due to scope. Eventhough the method is triggered successfully.
With similar problem I have able to use this to fix:
setTimeout(function(){
load1();
}, 5000);
function load1 () {
console.log('loaddd1..');
setTimeout(load2(), 4000);
}
function load2 () {
setTimeout(function(){
console.log('end load2');
}, 4000);
had this issue and clearInterval wasn't working.
make sure setInterval is only called once by wrapping it in an if statement:
var interval;
if (typeof(interval) === 'undefined') {
interval = setInterval(actFakeData,3000);
}
also helpful for me was assigning setInterval to a variable and console.log it so you can see the value throughout your code. for me when it was speeding up it was increasing in numeric value instead of resetting until I wrapped it in this.

Delay function from running for n seconds then run it once. (2minute question)

TLDR I have a function that runs on the end of a pan in an openlayers map. Don't want it to fire continously.
I have a function that runs on the end of panning a map.
I want it so that it will not fire the function until say 3 secconds after the pan has finished. Although I don't want to queue up the function to fire 10 or so times like setTimeout is currently doing.
How can I delay a function from running for n seconds then run it only once no matter how many times it has been called?
map.events.register("moveend", map, function() {
setTimeout(SetLocation, 5000);
});
Moveend:
moveend - triggered after a drag, pan, or zoom completes
The code above even using setTimeout(func, delay); still fires multiple times when it runs. How can I prevent this?
Well, meeting your requirements, you could build a simple function wrapper:
var executeOnce = (function (fn, delay) {
var executed = false;
return function (/* args */) {
var args = arguments;
if (!executed) {
setTimeout(function () {
fn.apply(null, args); // preserve arguments
}, delay);
executed = true;
}
};
});
Usage examples:
With your code:
map.events.register("moveend", map, executeOnce(SetLocation, 5000));
Other usages:
var wrappedFn = executeOnce(function (a, b) {
alert(a + ' ' + b);
}, 3000);
wrappedFn('hello', 'world');
wrappedFn('foo', 'bar'); // this won't be executed...
The wrapped function will be delayed the specified amount of time and executed only once.
For UI delays I would recommend using 'clearTimeout' in conjunction with 'setTimeout'. A call to 'setTimeout' returns an ID that is usually ignored. If, however, you store the ID, next time you are about to call 'setTimeout' you can cancel the previous 'setTimeout' (as though you never called it).
What I assume is happening in your case is:
(mouse move triggers callback)
setTimeout (1st)
(mouse move triggers callback)
setTimeout (2nd)
...
callback from 1st setTimeout is called
callback from 2nd setTimeout is called
...
If, however, you use clearTimeout, you'll have:
(mouse move triggers callback)
setTimeout (1st)
(mouse move triggers callback)
clearTimeout (1st)
setTimeout (2nd)
...
callback from last setTimeout is called
To update the JavaScript code you provided:
var delayedSetLocationId = -1;
...
map.events.register("moveend", map, function() {
if (delayedSetLocationId >= 0) {
clearTimeout(delayedSetLocationId);
}
delayedSetLocationId = setTimeout(SetLocation, 5000);
});
...
function SetLocation(...) {
delayedSetLocationId = -1; // setTimeout fired, we can't cancel it now :)
...
}
This is precisely what setTimeout is for. If setTimeout is calling the function 10 times, there's something wrong with your code, which you didn't post.
Also keep in mind that setTimeout will not halt the script.
I have actually written a small post about this. It is mush like what CMS has suggested.
The code snippet looks like this:
var delayonetimeaction = {
oneTimeActions: {},
/***
** Will wait the supplied "delay" until executing
** the supplied "action" (function).
** If called a second time before the with the
** same id, the first call will be ignored and
** instead the second will be used - that is the
** second action will be executed after the second
** supplied delay, not the first.
***/
bind: function (delay, id, action) {
// is there already a timer? clear if if there is
if (this.oneTimeActions[id]) clearTimeout(this.oneTimeActions[id]);
// set a new timer to execute delay milliseconds from last call
this.oneTimeActions[id] = setTimeout(function () {
action();
}, delay);
},
};
http://sds-digital.co.uk/post/2015/04/21/js-delayed-one-time-action.aspx

Categories