Scope
We have a function. Inside of it is an ajax request:
function search(){
$.ajax({
url: "url",
dataType: "text",
success: function(result) {
var filter = $(result).find('#myDiv');
// populate a hidden div with this information
$("#ladderInformation").html(filter);
}
});
}
Once this is complete, we iterate over the results of the initial ajax request, and run a new ajax request for each of them:
// yes, this is attached to the above, it's not outside of the first ajax call
.done(function(){
// for every team, we're going to run this ajax call
$('.team').each(function(i){
$.ajax({
url: "(we make use of $(this).text() here)",
dataType: "text",
success: function(teamdata){
$('#teamListing').append($(teamdata).find('#team-sheet'));
// for every time it runs, we'll append a div to the wrapper.
$('.wrapper').append('<div class="teamInfo" id="'+ Team [i] + '"></div>');
}
});
});
});
This is all working completely fine.
Next, I manipulate the elements received:
$(document).ajaxStop(function(){
//this function is irrelevant to the issue
configureTeams();
});
All of the above is wrapped in the first mentioned function, search();. We call this with
$(document).ready(function(){
search();
$('select').on('change', function(){
search();
});
});
On first page load it does everything as expected.
The Issue
When the select listener is fired multiple times, for every time it is used, the app drastically slows down. This was also noticed when I tried to add an "auto refresh" to the results (doing so by adding setTimeout(function(){ search() }, 5000); to the end of the $(document).ajaxStop(){} function).
For every time that search() is called, it will fire an additional time. So, for example, if you've changed select 6 times (or left the app running and auto refreshing for 6 times), it is firing 6 times to match this, and inevitably breaks.
Attempts to Fix
If I were to console.log() in the $(document).ajaxStop() function, it will fire an extra time for each time search() has been called. This can be combated by changing it to $(document).one('ajaxStop', function(){}) but that isn't solving the entire problem, since all that does is prevent the configuring from firing multiple times.
I have got the divs that hold the information emptying at the start of search(), so there are no conflicts with the same data or anything like that, I have tried managing the ajax requests in a queue, I have tried multiple methods of detecting that all of the ajax requests are finished before continuing, I have tried limiting the $.each() function so it doesn't exceed the required amount of iterations, but to no avail.
TL;DR
What I'm trying to accomplish, is that when I run a function multiple times, we completely start over each time. It seems as though it is recording each time it has been called. Could there be a solution with clearing memory, or the AJAX queue, or something like that?
I can provide the full code if that will be more helpful.
Thanks
I have a script that runs a long conversion php script and a progress polling script. After looking at several posts about this subject i found that it should be possible to use async ajax calls combined with timeout from javascript to create a construction that would poll the progress regularly and update my page with a percentile number. See code below
function startExcelConversion(excelname){
var poll = function(){
setTimeout(function(){
$.ajax({
url: "../include/ajax/ajax.php?action=poll_progress",
success: function(data){
//Update the progress bar
// show progress
console.log('progresser: '+data);
$("#progress").val(data);
//Setup the next poll recursively
poll();
},
complete: function( jqXHR, textStatus ){
//Update the progress bar
// show progress
console.log(textStatus);
},
dataType: "json"
});
}, 3000);
};
poll();
//show loading image
console.log('starting conversion');
$('#progress').val("Excel openen...");
$('#main').prepend('<img id="loading" src="../include/image/load.gif">');
$("#loading").show();
$.ajax({
url: '../import/import_main.php?clean&action=importexcel&excelname='+excelname,
success: function(data) {
console.log(data);
$("#main").html(data)
$('#loading').hide();
}
});
return false;
}
the first block launches the script that runs a while (excel reading and conversion).This script updates a database table every 10 rows to set the progress. the second block (from start polling onwards0 should launch a php script that reads this progress db field and echo it so i can update my input field with the percentile. However the polling script is not called during the runtime of the first php script (import_main.php). I tried $.post and $.get calls (which should as $.ajax be asynchronous by default). Also tried setInterval but that did not work and was not recommended due to timing problems. Am i missing something obvious here or is it a setting in php i am missing?
thnx in advance
I would try to define poll at the top of the script, like:
var poll = function(){
setTimeout(function(){
$.ajax({
url: "../include/ajax/ajax.php?action=poll_progress",
success: function(data){
//Update the progress bar
// show progress
console.log('progresser: '+data);
$("#progress").val(data);
//Setup the next poll recursively
poll();
},
dataType: "json"
});
}, 3000);
});
and then call it, like, poll(), after the ajax call. See if that helps. Right now, you have an anonymous function after the ajax call, but it tries to call itself with poll(); in the success callback, which isn't going to be defined.
it turned out the problem was threefold:
The first problem was indeed the use of an IIFE function that was not defined at runtime. So using inline function such as z416175 described was certainly valid
The second problem was that when a session is active in PHP it will block other (ajax) calls to prevent session overwriting. So using session_write_close() before entering the long running script worked to allow asynchronous ajax calls for progress updating. See this post (thnx to z416175) One ajax call block other ajax call
The third problem was that when you use xdebug the second problem remains because xdebug keeps a session open preventing the asynchronous ajax progress update call. So be aware when testing that xdebug causes problems with this
Thanks for all input. I have credited z416175's post for various usefull info in his answer and comments
I have a python script that's doing around 8 or 9 specific steps. These steps are being logged in a file. For web GUI to display status change, or error messages, I am using the script belowjquery PeriodicalUpdater plugin.
I need the program to run simultaneously so that as the value in the file changes,it gets polled and displayed.
Please find my jquery code below.
Note the url "/primary_call/" takes around 2 and half minutes to execute. Problem is async :false is not working. The browser waits for 2.5 minutes, and then gets into the next level.
I tried in Firefox and Chrome and it gives the same result.
When I call the URL of another browser tab, it works perfectly, but I am unable to run both script components simultaneously, when I try calling from the same page.
What should I do so that the browser initiates "/primary_call/", which runs a Python script in the background, at the same time moving ahead to the portion called PeriodicUpdate.
$(document).ready(function()
$.ajax({
type: 'GET', // Or any other HTTP Verb (Method)
url: '/primary_call/',
async: false,
success: function(r){
return false;
},
error: function(e){
}
});
$.PeriodicalUpdater({
url : '/static/12.txt',
method: 'post',
maxTimeout: 6000,
},
function(data){
var myHtml = data + ' <br />';
$('#results').append(myHtml);
});
})
Setting async:false means you are making the process synchronous, so the browser will hang on it until it is finished -- it can't move on to your other method. Removing that option will make the call asynchronous (which it is by default, as it should be) at which point the browser will initialize each ajax call in a separate thread.
In short, remove async:false.
I've made script which change information from different site, its occure when i click on button, sometimes it takes 1-2 seconds to find info and display it, sometimes 10 or more seconds. i made a script which change some table rows etc in timeOut 5 seconds, how can i set timeOut if i dont know how long this search will go
$("div.dreamcast input.btn").click(function() {
$.ajax({
success: function () {
setTimeout(function() {
//i want to change results information here
$('table.itt_results tbody tr:first th:contains("etc")').hide();
},
5000 //timeout 5s
);
});
Within the succes function of the jQuery ajax call, the code gets executed as soon as the AJAX call has been successful. This way, you don't have to know how long it takes, it will always be fine.
So no need for a setTimeout here.
The success method will only be executed when you have the result so you don't need the timeout function there.
The success function will only run when the ajax function has finished successfully. There's no need to guess how long it will take.
I'm just starting to wean myself from ASP.NET UpdatePanels. I'm using jQuery and jTemplates to bind the results of a web service to a grid, and everything works fine.
Here's the thing: I'm trying to show a spinner GIF while the table is being refreshed (à la UpdateProgress in ASP.NET) I've got it all working, except that the spinner is frozen. To see what's going on, I've tried moving the spinner out from the update progress div and out on the page where I can see it the whole time. It spins and spins until the refresh starts, and stays frozen until the refresh is done, and then starts spinning again. Not really what you want from a 'please wait' spinner!
This is in IE7 - haven't had a chance to test in other browsers yet. Any thoughts? Is the ajax call or the client-side databinding so resource-intensive that the browser is unable to tend to its animated GIFs?
Update
Here's the code that refreshes the grid. Not sure if this is synchronous or asynchronous.
updateConcessions = function(e) {
$.ajax({
type: "POST",
url: "Concessions.aspx/GetConcessions",
data: "{'Countries':'ga'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
applyTemplate(msg);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
}
});
}
applyTemplate = function(msg) {
$('div#TemplateTarget').setTemplate($('div#TemplateSource').html());
$('div#TemplateTarget').processTemplate(msg);
}
Update 2
I just checked the jQuery documentation and the $.ajax() method is asynchronous by default. Just for kicks I added this
$.ajax({
async: true,
...
and it didn't make any difference.
It's not the Ajax call that's freezing the browser. It's the success handler (applyTemplate). Inserting HTML into a document like that can freeze IE, depending on how much HTML there is. It's because the IE UI is single threaded; if you notice, the actual IE menus are frozen too while this is happening.
As a test, try:
applyTemplate = function(msg) {
return;
}
I don't remember precisely what caused it, but we had a similar issue with IE6 in a busy box and we fixed it with this incredible hack in the Javascript:
setTimeout("document.images['BusyImage'].src=document.images['BusyImage'].src",10);
That just sets the image source to what it was before, but it is apparently enough to jostle IE out of its stupor.
edit: I think I remember what was causing this: We were loading the animation into a div with display: none. IE loads it and doesn't start the animation, because it's hidden. Unfortunately it doesn't start the animation when you set the containing block to display: block, so we used the above line of code to trick IE into reloading the image.
The image freezes because while it is hidden the animation is disabled by IE.
To fix this, append the loading image instead of unhiding it:
function showLoader(callback){
$('#wherever').append(
'<img class="waiting" src="/path/to/gif.gif" />'
);
callback();
}
function finishForm(){
var passed = formValidate(document.forms.clientSupportReq);
if(passed)
{
$('input#subm')
.val('Uploading...')
.attr('disabled','disabled');
$('input#res').hide();
}
return passed;
}
$(function(){
// on submit
$('form#formid').submit(function(){
var l = showLoader( function(){
finishForm()
});
if(!l){
$('.waiting').remove();
}
return l;
});
});
Are you sure that its during the AJAX call that the GIF isn't spinning?
In your concessions.aspx place this line somewhere in the handling of GetConcessions:-
System.Threading.Thread.Sleep(5000);
I suspect that the gif spins for 5 seconds then freezes whilst IE renders and paints the result.
I know the question was regarding asynchronous ajax calls. However I wanted to add that I have found the following in my tests regarding synchronous ajax calls:
For Synchronous ajax calls. While the call is in progress (i.e. waiting for the server to respond). For the test i put a delay in the server response on the server.
Firefox 17.0.1 - animated gif continues to animate properly.
Chrome v23 - animated gif stops animation while the request is in progress.
well, this is for many reasons. First at all, when the ajax call back of the server, you will sense a few miliseconds your gif frozen, but not many relevant. After you will start to process information, and depending of the objects that you manipulate and how you do it, you will have more o less time your gif frozen. This is because the thread is busy processing information. Example if you have 1000 objects and your do a order, and move information, and also you use jquery and append, insert, $.each commands, you will senses a gif frozen. Sometimes it's imposible avoid all the frozen gifs, but yu can limit the time to a few miliseconds doing this: Make a list of response ajax, and process it each 2 seconds (with this you will have the results in a alone array and you wil call it with one setInterval and you avoid the bottle neck of try process one response when the before response is still processing). if you use JQuery don't use $.each, use for. Don't use dom manipulation (append,insert,etc..), use html(). In resume do less code, refactor, and procdess all the response (if you did more of 1) like only 1. Sorry for my english.
I had a similar problem with the browser freezing. If you are developing and testing locally, for some reason it freezes the web browser. After uploading my code to a web server it started to work. I hope this helps, because it took me hours to figure it out for myself.
I have seen this behavior in the past when making AJAX calls. I believe this is related to the fact that browsers are only single threaded, so when the AJAX call is returned the thread is working on the call, so consequentially the animated GIF needs to stop momentarily.
dennismonsewicz's answer is greate. Use spin.js and the site http://fgnass.github.com/spin.js/ shows the step which is quite easy.
Under heavy process we should use CSS animations.
No JS driven animations and GIFs should be used becacuse of the single thread limit otherwise the animation will freeze. CSS animations are separated from the UI thread.
Are you doing a synchronous call or asynchronous call? synchronous calls do cause the browser to seemingly lock up for the duration of the call. The other possibility is that the system is very busy doing whatever work it is doing.
Wrapping ajax call in setTimeout function helped me to prevent freezing of gif-animation:
setTimeout(function() {
$.get('/some_link', function (response) {
// some actions
});
}, 0);
Browsers are single-threaded and multi-threaded.
For any browser :
When you a called a function that contains a nested ajax function
java/servlet/jsp/Controller >
keep Thread.sleep(5000); in servlet to understand the async in ajax when
true or false.
function ajaxFn(){
$('#status').html('WAIT... <img id="theImg" src="page-loader.gif" alt="preload" width="30" height="30"/>');
$('#status').css("color","red");
$.ajax({
url:"MyServlet",
method: "POST",
data: { name: $("textarea").val(),
id : $("input[type=text]").val() },
//async: false,
success:function(response){
//alert(response); //response is "welcome to.."
$("#status").text(response);
$('#status').css("color","green");
},
complete:function(x,y){
//alert(y)
},
error:function(){
$("#status").text("?");
}
});
}