Delay JS asynchronously until the condition is met

I have a ChatRoom class that can only be displayed after receiving a long HTTP request (this may take 1 second or 30 seconds). So I need to delay rendering until ChatRoom.json is null.

In the code below, I am using the Closure Library goog.async.ConditionalDelay . It works, but is there a better way (maybe without the 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) {}" is not possible because it will be synchronous (blocking all other JS execution).

+6
source share
3 answers

Consider this:

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

This will be checked every half second.

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

+20
source

You can also achieve this using the lodash debouncer with recursion.

 import _debounce from 'lodash/debounce'; const wait = (() => { if ( chatroom.json ) { chatroom.render(); } else { _debounce(wait, 500)(); } })(); 
0
source

The answer I came up with is as follows:

 var count = 0; // Number of functions that need to run. This can be dynamically generated // In this case I call check(data, cb) a total of 3 times var functionNum = 3; function toCallAfter(){ console.log('I am a delayed function'); } 

I had this for a validation function that ran once regularly and twice in a loop:

 check(data, function(err){ // check is my asynchronous function to check data integrity if (err){ return cb(null, { // cb() is the return function for the containing function errCode: 'MISSINGINFO', statusCode: 403, message : 'All mandatory fields must be filled in' }); } // This part here is an implicit else count++; // Increment count each time required functions complete to // keep track of how many function have completed if (count === functionNum) { return anon(); } return; }); // Run twice more in a loop for(var i = 0; i < 2; i++) { check(data, function(err) { // calls check again in a loop if (err){ return cb(null, { errCode: 'MISSINGINFO', statusCode: 403, message : 'All mandatory fields must be filled in' }); } count++; if (count === functionNum) { return toCallAfter(); } return; }); } 

Finally, I would like to point out a significant performance error of the alternative (and unusually general) answer:

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

In this case, you essentially keep the browser or server (when using node.js) hostages for 500 milliseconds for each scan, which is an incredibly long time for the computer. It means a huge success. My solution to directly track the required completed functions does not contain time limits and will start immediately after all functions are completed.

-1
source

Source: https://habr.com/ru/post/898097/


All Articles