admin管理员组

文章数量:1425753

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 plete 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;
   });
}

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 plete 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;
   });
}
Share Improve this question asked Jul 13, 2012 at 17:01 doub1ejackdoub1ejack 11.2k20 gold badges77 silver badges130 bronze badges 2
  • 2 I don't understand your issue. Callbacks are a standard part of programming. What do you mean by "dictates how & where my code is written which I don't love"? – scott.korin Commented Jul 13, 2012 at 17:09
  • 1 @scott.korin I believe he means that it typically used to require that the programmer either pass around callback handlers all over, and/or excessively nest anonymous functions. $.Deferred is the answer to both problems. – Alnitak Commented Jul 13, 2012 at 17:13
Add a ment  | 

5 Answers 5

Reset to default 8

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.

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 plete 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.

本文标签: javascriptWhy can39tshouldn39t I use a while loop to monitor asynchronous jQuery operationsStack Overflow