Question

I am trying to wrap my head around coordinating asynchronous operations. I need a little help understanding:

  1. Why using a while loop to wait for an operation to complete is a bad idea and doesn't work, and
  2. If there are viable alternatives to using callbacks on the jQuery functions

Most of the time, adding a callback to an asynchronous function like $.get() works great. However this does, to some degree, dictate how & where my code is written which I don't love.

$(function() {

    var r = AjaxResults( page );

    // loop prevents further processing until GetResults() is done
    while( isComplete == false )
    isComplete = $('body').data('isComplete');

    // reset isComplete boolean
    $('body').data('isComplete', false);

    // this will only continue after GetResults() has exited
    paintTheTownRed();
    var whateverElse = true;
});

function AjaxResults( page ) {

   // do something before async operation
   switch( page ){
       case '1': {...} break;
       ...
       default: break;
   } 

   $.getJSON("/controller/page", null, function(data) {

       // do something after async operation
       {...}

       $('body').data('isComplete', true);
       return data;
   });
}
Was it helpful?

Solution

Because it will spike my CPU and irritate me greatly.

Where you write your code is almost never dictated by asynch/synch; functions are functions, whether they're anonymous and written in-line, or named and passed as a reference.

Also, promises and deferred objects help in deciding where/how to implement functionality.

See things like .when (docs) for additional details and ideas, but there are other ways to use them.

OTHER TIPS

In a nutshell, you shouldn't do this because it will be a very bad user experience and it will seriously irritate most/all your viewers. At best it will spike the CPU and needlessly drain the viewer's battery. At worst, the viewer will think their browser froze/hung.

Because javascript is single threaded and that single threadedness is tied to the user event handling in the browser, if you use a while loop to loop waiting for an async event to finish, you will lock up the browser during the time of the while loop. You will probably also find that some browsers will give the user a warning about excessively long running javascript.

There are NOT currently alternatives to callbacks of some type for asynchronous programming in javascript. If you want to use asynchronous operations, then you MUST adapt your programming style to how they work in order to maintain a good user experience. Yes, this means adapting your programming style, but that is the price to pay in order to maintain a good user experience. Deferred objects can give you a slightly more pleasing style of writing code (it's still callbacks, but seems a little less so) if you want to investigate that.

To do what you were proposing would be to prioritize your programming convenience ahead of the user experience which is only the sign of a bad/lazy programmer who seems to have their objectives/priorities backwards.

FYI, this would be a bad programming practice even in environments where it's allowed and would work (like native Windows development).

Most of the time, adding a callback to an asynchronous function like $.get() works great. However this does, to some degree, dictate how & where my code is written which I don't love.

There's no need to add callbacks to AJAX functions directly any more.

Use jQuery deferred objects to let you write your code where you want without excessive nesting:

function AjaxResults( page ) {
    ...  // prep
    return $.getJSON("/controller/page", null)
        .done(function(data) {
            // always do this
        });
}

AjaxResults(page).done(paintTheTownRed);

By all means put your own complete handler on $.getJSON as shown here, but by returning the jqXHR object you get the chance to do extra stuff without having to pass lots of callbacks around or nest your code.

If your problem is that you don't like defining the function that gets called in the $.get(), then by all means write that as a separate function:

$(function() {

    AjaxResults( page );

});

function AjaxResults( page ) {

   // do something before async operation
   switch( page ){
       case '1': {...} break;
       ...
       default: break;
   } 

   $.getJSON("/controller/page", null, doWhatever);
}

function doWhatever(data) {
    paintTheTownRed();
    var whateverElse = true;
}

Well, it's a bad idea because it doesn't work. The callback function is never called because you are in the while loop, so the boolean is not changed to true and so it is an infinite loop

Now, why actual sync requests are a bad idea is because they freeze the UI and make me think the tab crashed. But yes, sync requests are an alternative to callbacks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top