50

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.

Herb Caudill
  • 50,043
  • 39
  • 124
  • 173

12 Answers12

32

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;
}
Chase Seibert
  • 15,703
  • 8
  • 51
  • 58
  • You are correct sir. I guess I need to either (a) live with it or (b) find a more efficient templating engine. – Herb Caudill Oct 10 '08 at 16:45
  • 13
    `more efficient` BROWSER is more like it! – kralco626 Apr 11 '11 at 11:24
  • I had the same thing happen IE. This is caused by the browser rendering the HTML back after the ajax call. Didn't happen in Chrome or FF :/ – webtrifusion Sep 30 '11 at 15:37
  • 17
    This appears to be happening to me in Chrome?!? – Ben Jul 17 '12 at 18:18
  • 15
    This is happening to me as well, but my GIF file stops animating in ALL BROWSERS except for Opera. I tested with IE9, FF, Chrome, Opera, and Safari. In Opera, the GIF file animated, but it was sluggish. My guess is that Opera is yielding some time to screen redraws. But with all other browsers, the GIF file completely locked up when I was rendering and blasting HTML into a container in response to an AJAX call. I know the tendency is to blame IE for everything, but in this case IE's behavior is identical to FF, Chrome, and Safari. – Armchair Bronco Oct 10 '12 at 21:31
  • It works if you put the gif as content in an iframe, even in IE. – Björn May 23 '13 at 02:50
  • @ArmchairBronco: Even in my case loading gif freezes in all browsers except opera while rendering the template. How did you handle this freezing? – Raeesaa Aug 05 '14 at 10:11
  • You can start it up again by setting the image source to itself after the ajax call. (image.src = Image.src) for IE. – Jason Gilley Feb 10 '15 at 22:09
  • 1
    Here's the best answer I've found: http://stackoverflow.com/questions/7440897/loading-spinner-gif-image-gets-stuck/7442178#7442178 – Circle B Apr 18 '15 at 15:55
8

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.

Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
David
  • 3,177
  • 1
  • 18
  • 15
7

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;
    });
});
ruffrey
  • 6,018
  • 3
  • 23
  • 19
5

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.

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
4

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.

user1650613
  • 137
  • 1
  • 3
  • IE test show results similar to Chrome - I was able to change the call to asynchronous but that may not help others – eslsys Oct 10 '13 at 15:04
3

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.

2

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.

Matt
  • 31
  • 1
1

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.

Chris Pietschmann
  • 29,502
  • 35
  • 121
  • 166
  • I doubt that this is an unavoidable consequence of browser architecture - when using UpdatePanel/UpdateProgress controls in ASP.NET (which result in an ajax call behind the scenes), animated GIFs work just fine. – Herb Caudill Oct 10 '08 at 14:30
  • It think you'll find that GIF animation is happening on a different thread than the one that Javascript runs in. My guess is the pause occurs at a point inside the code where innerHTML is assigned new content. – AnthonyWJones Oct 10 '08 at 15:08
1

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.

Siri How
  • 113
  • 3
  • 10
0

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.

Steve g
  • 2,471
  • 17
  • 16
0

Wrapping ajax call in setTimeout function helped me to prevent freezing of gif-animation:

setTimeout(function() {
    $.get('/some_link', function (response) {
        // some actions
    });
}, 0);
yesnik
  • 4,085
  • 2
  • 30
  • 25
-1

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("?");
        }
    });
}
 
Venkat
  • 157
  • 3