Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait to return from a javascript function until condition met

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.

like image 603
findchris Avatar asked Dec 01 '11 03:12

findchris


People also ask

How do I make a function wait before returning?

Promises handled with async/await To solve this with modern features, place the keyword async before the functions. Doing this enables the use of the keyword await within them. When used before some code that returns a promise, await prevents further function execution until the promise is returned.

How do you wait for a function to finish before continuing JavaScript?

– Async Function-Based Promises: Use the “Await” Function For async function-based promises, you may add the “await” function to stop the function in javascript, until the promise is fulfilled, and then return the result value.

How do you stop a JavaScript function when a certain condition is met?

You can do it using the return keyword. Whenever JavaScript sees the return keyword, it immediately exits the function and any variable (or value) you pass after return will be returned back as a result.

What is delay () in JavaScript?

The delay is set in milliseconds and 1,000 milliseconds equals 1 second. If the delay is omitted from the setTimeout() method, then the delay is set to 0 and the function will execute. You can also have optional arguments that are passed into the function.


2 Answers

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);
like image 131
Jordão Avatar answered Oct 18 '22 02:10

Jordão


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;
}
like image 30
six8 Avatar answered Oct 18 '22 01:10

six8