Wait to return from a javascript function until condition met

99封情书 提交于 2019-12-04 19:32:48


This is an odd problem. I have a client object that I am building up using Crockford-esque public/private members:

var client = function() {
  var that, remote_data, other_data; 

  // add public interface
  that.doStuff = function(){...}

  // wait for remote resources to load
  remote_data = jsonRequest1();
  other_data  = jsonRequest2();

  return that;

The problem I'm having is that I need to load some remote JSON resources prior to returning the new 'that' object (which signals a ready client). Data is returned asynchronously (obviously), and I am setting boolean variables to indicate when each remote resource has returned.

I've thought about doing something like the following:

return whenInitialized(function() { return that; });

The whenInitialized function returns whether or not both of the boolean flags are true. I'd use this with a combination of setInterval, but I am sure this won't work.

Would appreciate your suggestions.


In order to run code after an asynchronous operation has succeeded, you need a continuation. It can be just a callback that your code calls when the operations are complete.

Something like this:

var client = function(done) { // done is the callback
  var that, remote_data, other_data; 

  // add public interface
  that.doStuff = function(){...}

  // wait for remote resources to load
  var done1 = false, done2 = false;
  var complete1 = function() { done1 = true; if (done2) done(); };
  var complete2 = function() { done2 = true; if (done1) done(); };
  remote_data = jsonRequest1(complete1);
  other_data  = jsonRequest2(complete2);

  return that;

But these controlling flags are really annoying and don't really scale. A better, declarative way of doing this is using something like jQuery deferreds:

$.when(jsonRequest1(), jsonRequest2()).then(done);


You can do a loop (optionally with a timeout) to wait for the async to finish. Warning, this will (as requested) block all other functionality and may cause the browser to freeze if it takes much too long. However, you really should figure out an asynchronous way to do what you need instead of blocking like this.

var syncRequest = function(options) {
    var is_finished = false;
    var result;
    var finished_callback = function(response) {
        is_finished = true;
        result = response.result;

    ajax_request(options, finished_callback);

    // timeout in 30 seconds
    var timeout = (new Date()).getTime() + 30000;
    while ( !is_finished ) {
        if ( (new Date()).getTime() >= timeout ) {
            alert('Request timed out');

        // do nothing, just block and wait for the request to finish

    return result;