Asynchronously delay JS until a condition is met

Amy B picture Amy B · Sep 26, 2011 · Viewed 15.4k times · Source

I have a class, ChatRoom, that can only render after it receives a long-running HTTP request (it could take 1 second or 30 seconds). So I need to delay rendering until ChatRoom.json is not null.

In the code below, I'm using Closure Library's goog.async.ConditionalDelay. It works, but is there a better way (maybe without needing Closure Library) to do this?

ChatRoom.prototype.json = null; // received after a long-running HTTP request.

ChatRoom.prototype.render = function() {
    var thisChatRoom = this;

    function onReady() {
        console.log("Received JSON", thisChatRoom.json);
        // Do rendering...
    }

    function onFailure() {
        alert('Sorry, an error occurred. The chat room couldn\'t open');
    }

    function isReady() {
        if (thisChatRoom.json != null) {
            return true;
        }
        console.log("Waiting for chat room JSON...");
        return false;
    }

    // If there is a JSON request in progress, wait until it completes.
    if (isReady()) {
        onReady();
    } else {
        var delay = new goog.async.ConditionalDelay(isReady);
        delay.onSuccess = onReady;
        delay.onFailure = onFailure;
        delay.start(500, 5000);
    }
}

Note that "while (json == null) { }" isn't possible because that would be synchronous (blocking all other JS execution).

Answer

Šime Vidas picture Šime Vidas · Sep 26, 2011

Consider this:

(function wait() {
    if ( chatroom.json ) {
        chatroom.render();
    } else {
        setTimeout( wait, 500 );
    }
})();

This will check every half second.

Live demo: http://jsfiddle.net/kBgTx/