Calling a function inside itself using setTimeout - javascript

I want to call a function within itself like this:
$(document).ready (
function ready() {
var tester = $.ajax({
async: false,
url: "test_parse.php"
}).responseText;
document.getElementById('test').innerHTML = tester;
setTimeout(ready(), 3000);
}
);
But every time I do this my browser just keeps loading and eventually Apache shuts down (obviously not my expected result). Could you help me to figure out a solution?

setTimeout takes a function reference:
setTimeout(ready, 3000);
not
setTimeout(ready(), 3000);
And that being said, I would also do this:
$(document).ready (
function ready() {
var tester = $.ajax({
url: "test_parse.php",
success: function (data) {
document.getElementById('test').innerHTML = data;
setTimeout(ready, 3000);
}
})
}
);
Because async: false will lock up the browser until that data returns from the server

This is wrong:
setTimeout(ready(), 3000);
This is right:
setTimeout(ready, 3000);
ready() is actually invoking the function. ready is simply a reference to the function, which is what you want.

setTimeout expects a function reference as the first parameter, you have a function invocation which is passing the result of calling ready().
This is causing an infinite loop.
You need to pass in "ready", not "ready()"
setTimeout(ready, 3000);
And if you're trying to queue ajax requests that happen in a structured order, you'll want to fire the setTimeout on success after the previous ajax call, not immediately, otherwise you'll have ajax results returning and updating at arbitrary intervals depending on how the server responds to each request.
$.ajax({
// your ajax settings
}).success(function () {
// fire off the next one 3 secs after the last one completes
setTimeout(ready, 3000);
});
This is better than using the async: false setting, which blocks the browser.

Why are you trying to call the function within itself? Surely all you need to do is move setTimeout outside of the function, then call ready() every 3000ms? What'l do you want your output to be?

Related

Javascript doesn't update variables written with PHP

I have a javascript function that calls an AJAX, like this:
function addSquadronByID(id) {
$.ajax
({
type: "POST",
url: "server/get_squadron.php",
data: {
'id': id,
'counter': squadron_counter
},
cache: false,
success: function (data) {
squadron_counter++;
},
error: function () {
alert("AJAX error.");
}
});
}
}
Outside the document.ready, the variable is initialized like this var squadron_counter = 0;
This function perfectly works while I call it in the page, but if I try to use PHP to write it in the page, like this:
$list_squadrons = $DB->Execute($query);
while(!$list_squadrons->EOF){
$currentSquadron_id = $list_squadrons->fields["squadron_id"];
$currentSquadron_number = $list_squadrons->fields["squadrons"];
echo "addSquadronByID($currentSquadron_id);\n";
$list_squadrons->MoveNext();
}
The function writes into the document.ready() the correct calls, but squadron_counter is always zero, even if the function works. My only idea is that it works this way because javascript calls all the functions at once and does not wait to complete the first one before executing the second one, etc.. but how do I solve this?
HTML output as requested:
addSquadronByID(3, squadron_counter);
addSquadronByID(5, squadron_counter);
addSquadronByID(6, squadron_counter);
This is put into a
$( document ).ready(function() {
});
inside a <script> tag.
I think your idea about JS calling all functions without waiting for the first one to complete is in the right direction. This is called "asynchronous requests". Please refer to How to return the response from an asynchronous call? for a detailed explanation.
The idea is to send your 3 requests and then wait for all of them to complete before checking the value of your squadron_counter variable (or whatever data you have updated in your success callbacks).
Then if my understanding is correct, you do not know how to implement this waiting?
Since you are using jQuery, the implementation is super simple. Note first that your jQuery.ajax request returns a Deferred object. So simply keep a reference of the Deferred object created by each AJAX request you send. Then you could use for example jQuery.when with a callback in its then method to wait for all your requests to complete:
function addSquadronByID(id) {
return jQuery.ajax({ /* ... */ }); // returns a Deferred object.
}
var d1 = addSquadronByID(3),
d2 = addSquadronByID(5),
d3 = addSquadronByID(6);
jQuery.when(d1, d2, d3).then(
// callback executed on success of all passed Deferred objects.
function () {
console.log(squadron_counter);
}
);
Demo: http://jsfiddle.net/btjq7wuf/

jQuery IIFE, interject on demand?

I have a IIFE that self-fires on load and recursively calls itself every 30 seconds to get any alerts the system may have written out.
This works fine.
(function GetAlerts() {
setTimeout(function() {
$.ajax({ url: "?DO=getalertcount", success: function(data) {
//do DOM stuff with data
}, complete: GetAlerts });
}, 30000);
})();
There are things I will do, such as stop a widget, that write to the alert queue. As such, that should immediately trigger an alert to display, not wait up to 30 seconds for it to fire. (sockets and long polling are not an option due to server constraints)
So, I want to call this GetAlerts() on demand in some fashion from the handler of the action (such as stopping the widget click event)
What is the proper way to on-demand call this so that
the 30 second loop is retained (or re-started after the on-demand interject)
I don't end up with multiple setTimeout loops running
I don't duplicate a ton of code (as there is a lot of DOM stuff that happens in the guts of the success
The things I tried such as calling the function by name, attempting to set the timeout to a global var and stopping the timeout all failed one of the above points or simply did not invoke at all.
Move setTimeout to the success handler and use clearTimeout keep single loop running.
A class with public .poll method might help:
function AlertManager() {
var successCallback = function (data) {
// Private ajax success handler
//do DOM stuff with data
$('#responses').append('Polled!<br/>');
},
_poll = function () {
$.ajax({
url: "/echo/json/",
success: successCallback,
complete: function () {
timeoutId = setTimeout(_poll, timeoutMs);
}
});
},
timeoutId,
timeoutMs = 5000;
this.poll = function () {
clearTimeout(timeoutId);
_poll();
};
}
Take a look at the fiddle demo: http://jsfiddle.net/neustroev_ai/64on18zg/
Hope this helps!

setTimeout behavior with jquery and ajax

It is my understanding that setTimeout() can be used to stop code from executing temporarily, however this doesn't seem to be the case in the following code:
...}).done(function recursionLoad(){
var timerLoad = setTimeout(function(){
},3000)
$.ajax({
type:'GET',
url:'modelBN.xml',
beforeSend: function(){$('#query-results').html('<img src="images/ajax-loader.gif"><p>Loading...</p>'); },
timeout: 10000,
error: function(xhr, status, error){...
So what happens is the AJAX call get made immediately instead being delayed for 3 seconds. Am I just using setTimeout incorrectly or is there something about AJAX that prevents it from working? Thanks for any assistance
setTimeout will call the function you pass to it (in the first argument) after the time you specify in the second argument.
It is not a sleep function, and it won't block other code from running.
If you want to run your call to $.ajax after the time has elapsed, then you need to do so from the function you pass to setTimeout (as opposed to calling setTimeout (with a function that will do nothing after 3 seconds) and then immediately calling $.ajax).

jQuery/Javascript: 2 function calls in line, wait for the other to finish?

I know this might sound silly but I have no idea how to do that …
$('#someButton').click(function(e) {
e.preventDefault();
// Do ajax stuff
triggerAjaxSubmit('#signUpForm', false);
modalSlide(modal, $('.loginTab'), $('.saveTab'));
});
On click on #someButton I want to submit an entire form via ajax. The function that does this is called triggerAjaxSubmit. This function has a simple $.ajax() function provided by jquery and does something on either success or error.
So what I wonder is how I can delay the next line modalSlide() until I get a success or error from the triggerAjaxSubmit() function. Right now triggerAjaxSubmit() gets fired and immediately after it the modalSlide() function fires. However I want the modalSlide() function only to fire once a success or error comes back.
Can I do that somehow? I mean like return "success" inside of the ajax() call and only than fire the modalSlide() function?
thank you in advance.
Kind regards,
Matt
edit:
function triggerAjaxSubmit(formId, reset, callback) {
$(formId).ajaxSubmit({
type: "POST",
cache: false,
resetForm: reset,
dataType: "text json",
success: function(jsonObject, status) {
// some other stuff
console.log('success');
},
error: function(requestObject, status) {
console.log('error');
}
});
}
triggerAjaxSubmit(form, true, function() {
console.log('this is not happning')
modalSlide(modal, $('.loginTab, .signUpTab'), $('.saveWeaveTab'), $('#newWeaveForm_title'));
});
You could return the deferred that $.ajax returns in triggerAjaxSubmit. Something like:
function triggerAjaxSubmit( .. ) {
return $.ajax({ .. });
}
and:
triggerAjaxSubmit( .. ).done(function() {
modalSlide( .. );
});
Edit: With the form plugin, you should be able to do this:
function triggerAjaxSubmit( .. , callback ) {
$( .. ).ajaxSubmit({
.. ,
success: function() {
console.log("success");
callback();
})
});
}
and:
triggerAjaxSubmit( .. , function() {
modalSlide( .. );
});
You need to call your modalSlide function from the callback in your $.ajax() call.
AJAX calls are asynchronous (unless you use the questionable async: false option in jQuery), so if you want to execute some code when the AJAX request receives a response, you'll need to put it in the success callback.
Depending on the rest of your code, this may be as simple as modifying the triggerAjaxSubmit function so that the callback supplied to the $.ajax() function includes the relevant code.
Or you may need to modify it a bit more to take a function as an argument, which is then provided as the success callback for the $.ajax() function.
Edit: I missed the "or error" in the question, hence why I only referred to the success callback. Same principle applies for the error callback, though.
call modalSlide function in success parameter of $.ajax() call

Setting timer after an asynchronous call returns

I have an asynchronous Ajax function which runs a command string at the server side and returns the result to the client. It calls a callback to process the result.
function ajaxCall(commandStr,callback){
var url=......//make a url with the command string
jquery.get(url,function(result){
//process the result using callback
callback(result);
});
}
The asynchronous call (ajaxCall) may take a while to be finished but I want it to do the same command after an interval (1000ms).
I want to write a function that is like this:
function ajaxCallRepeated(interval,commandStr,callback)
I tried closures like this:
function ajaxCallRepeated(interval,commandStr,callback){
//This feature uses closures in Javascript. Please read this to know why and how: http://jibbering.com/faq/notes/closures/#clSto
function callLater(param1,param2,param3){
return (function(){
ajaxCall(param2,function(out,err){
if(param3)param3(out,err);
var functRef = callLater(param1,param2,param3);
setTimeout(functRef, interval);
});
});
}
//the first call
var functRef = callLater(interval,commandStr,callback);
setTimeout(functRef, interval);
}
Then I call it like this:
ajaxCallRepeated(2000,"ls",function(result){
alert(result);
});
But it only runs the command 2 times.
How can I write a function that will reschedule itself after it is called as a callback of an asynchronous function?
PS. I want to fire another Ajax call after the previous one is finished. Also, it worth to mention that axashCallRepeated() will be called with various parameters, so several Ajax calls are running in parallel, but for each commandStr, there is only one Ajax call going on, and after the Ajax call returns, another one will be fired after X seconds.
I would not use setTimeout to trigger the second Ajax call ! Because you never know how long it will take and if it's finished !
As far as you tagged your question right and you ARE using jquery you should consider something like this:
$.ajax({
type: 'POST',
url: url,
data: data,
success: function(){
// The AJAX is successfully done, now you trigger your custom event:
$(document).trigger('myAjaxHasCompleted');
},
dataType: dataType
});
$(function(){
//somehwere in your document ready block
$(document).on("myAjaxHasCompleted",function(){
$.ajax({
//execute the second one
});
});
});
So this would ensure that the ajax post is DONE and was successful and now you could execute the second one. I know its not the exact answer to your question but you should consider on using something like this ! Would make it safer I guess :-)
The key to solve this problem is to save a reference to the closure itself and use it when scheduling the next call:
function ajaxCallRepeated(interval,commandStr,callback){
//This feature uses closures in Javascript. Please read this to know why and how: http://jibbering.com/faq/notes/closures/#clSto
function callLater(_interval,_commandString,_callback){
var closure=(function(){
ajaxCall(_commandString,function(out,err){
if(_callback)_callback(out,err);
setTimeout(closure,_interval);
});
});
return closure;
}
//now make a closure for every call to this function
var functRef = callLater(interval,commandString,callback);
//the first call
functRef();
}
It becomes easier to reason about if you separate things up a bit.
For example, the repetition logic doesn't have to know about AJAX or callbacks at all:
function mkRepeater(interval, fn, fnScope, fnArgs) {
var running;
function repeat() {
if (!running) return;
fn.apply(fnScope, fnArgs);
setTimeout(repeat, interval);
}
return {
start: function() { running = true; repeat(); },
stop: function() { running = false; }
};
}
You can use it like this:
var r = mkRepeater(2000, ajaxFunction, this, ["getStuff", callbackFn]);
r.start();
...
r.stop();

Categories

Resources