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).
The answer I came up with is like this:
I had this for a check function that ran once regularly and twice in a loop:
Lastly, I'd like to point out a significant performance fault in the alternate (and extraordinarily common) answer:
In this case, you are essentially holding the browser or server (If using node.js) hostage for 500 milliseconds for every check which is an incredibly long time for a computer. Meaning a huge performance hit. My solution of directly keeping track of the required completed functions is free from time restraints and will run instantly as soon as all functions complete.
You could also achieve this using lodash's debouncer with recursion.
Consider this:
This will check every half second.
Live demo: http://jsfiddle.net/kBgTx/