Why does my spinner GIF stop while jQuery ajax call is running? - javascript

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("?");
}
});
}

Related

Ajax call stops after a certain amount of PHP loops (2 minutes)

I have a button that checks a lot (300+) posts for a specific value and other things (about 20 if, else's). Somehow the ajax call of the button stops after looping about 73 times/2mins.
It doesn't loop this ajax call, there's a PHP loop in the function it's referring to.
Is there any way to extend this? This is what I currently have:
$.ajax({
url: ajaxurl + "?action=updatefield",
type: 'post',
data: dataString,
success: function(data) {
console.log("SUCCESS!");
$("#myResponse").html("<h4>Response: </h4><hr>" + data);
},
error: function(data) {
console.log("FAILURE");
},
timeout: 600000 // (this is what I tried, but it doesn't seem to work)
});
Perhaps this is the answer for my problem, but not my question: Browser Timeouts
Is there a way to extend this time, or is there another way?
So let me get this right... you have ONE Ajax call that triggers a PHP loop, and it's the PHP loop that times out?
It could be:
An HTTP timeout (this can be increased in the Apache config, but it's not recommended)
An HTTP body size overflow (again this can be increased in the Apache config, but it's not recommended)
A server-side limit on the maximum execution time of a PHP script (this can be changed in php.ini, but guess what... it's not recommended!)
Ultimately you are not doing this right. You should be calling the PHP script every so often (for example every second) by putting the Ajax call in a JS setInterval(1000); The PHP script itself should be quick and to the point.
I have tracked down the issue by enabling PHP errors. Besides fixing common errors, I found the issue.
Allowed memory size of 134217728 bytes exhausted
I'm currently trying to clean up my code and remove any unnecessary requests to increase speed and efficiency. Thanks for all the answers.

Function firing additional time for each time it is called - jQuery/AJAX

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

setInterval() not stopping on time, "jumping" between intervals

I'm building a web app to help with a restaurant, and my client was very clear on that he wanted the app to be asynchronous.
During localhost development I used setInterval to update the page periodicaly using variations of this code for each button:
$('#showWaitlist').click(function(){
showWaitlist();
stopUpdate(interval);
interval = setInterval(function() { showWaitlist();}, intervalTime);
});
function stopUpdate(){
clearInterval(interval);
}
So that every time I click a button it stops the past interval and starts it's own.
It worked fine, however, when I moved the app to the server the intevals would sometimes overlap each other, specially when the server was on heavier-than-avarage load or when I used a phone to access the site.
If setInterval and stopUpdate are js shouldn't they work on clientside and be practically instant? What could cause this "jumping" between intervals?
This is a link to the website: http://www.emc2.mx/Pruebas/unicenta/PostodoroApp/
Please note that the problem not always happens, but you can probably replicate it if you opne it on your phone.
I'll add showWaitlist here, but I doubt there's something wrong with it.
function showWaitlist(){
$.ajax({
type:'GET',
url: 'waitlist.php',
dataType: 'html',
success: function(result){
$('#result_table').html(result);
} // End of success function of ajax form
}); // End of ajax call
}
You will need to clear the interval in
the success of the ajax call on your code by adding the following line
clearInterval(interval); // stop the timer once the time finishes.
after the following line
$('#result_table').html(result);
You need to have access of the interval variable in the success method callback

jquery ajax async false is not working

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.

jQuery-ajax call: async property is not working?

given to certain circumstances, I'm forced to keep page settings (Javascript-values) in the session and it has to be done right before leaving the page (I can't use cookies, since "pageSettings" can become quite large and localStorage is not an option yet ;) ). So this is how I tried it. However it seems that when I call the page directly again, the call of "http://blabla.com/bla" happens asynchronous, even though the async-attribute is set (I don't receive the settings of the previous call, but of the one before):
$jQ(document).ready(function () {
$jQ(window).unload(Main.__setSessionValues);
});
var Main = {
pageSettings: {},
__setSessionValues: function __setSessionValues() {
$jQ.ajax({
type: "POST",
async: false,
url: "http://blabla.com/bla",
data: {
pageSettings: Object.toJSON(Main.pageSettings)
}
});
}
};
Does anyone know what the problem might be?
thanks in advance
The code looks fine. You might try bind('beforeunload', ...) rather than unload, to grab things as early as possible. But of course, if something else also hooks beforeunload and the unload gets cancelled, your call will have been made even though you're still on the page.
Slightly off-topic, but if you can possibly find a different way to do this, I would. Firing off synchronous ajax calls when the user is trying to leave the page is not ideal.

Categories

Resources