Skip to content Skip to sidebar Skip to footer

How To Make A Javascript FOR LOOP Wait For Certain Conditions Before Looping

I have to call up a function (checkImdb) that will fetch some info from a php file (temp.php) and put some contents on a div (placeToFetchTo). This has to be done a certain amount

Solution 1:

2017 update: The original answer had the callback arg as last arg in the function signature. However, now that the ES6 spread operator is a real thing, best practice is to put it first, not last, so that the spread operator can be used to capture "everything else".


You don't really want to use a for loop if you need to do any "waiting". Instead, use self-terminating recursion:

/**
 * This is your async function that "does things" like
 * calling a php file on the server through GET/POST and
 * then deals with the data it gets back. After it's done,
 * it calls the function that was passed as "callback" argument.
 */
function doAsynchronousStuff(callback, ...) {
  //... your code goes here ...

  // as final step, on the "next clock tick",
  // call the "callback" function. This makes
  // it a "new" call, giving the JS engine some
  // time to slip in other important operations
  // in its thread. This basically "unblocks"
  // JS execution.
  requestAnimationFrame(function() {
    callback(/* with whatever args it needs */);
  });
}

/**
 * This is your "control" function, responsible
 * for calling your actual worker function as
 * many times as necessary. We give it a number that
 * tells it how many times it should run, and a function
 * handle that tells it what to call when it has done
 * all its iterations.
 */
function runSeveralTimes(fnToCallWhenDone, howManyTimes) {
  // if there are 0 times left to run, we don't run
  // the operation code, but instead call the "We are done"
  // function that was passed as second argument.
  if (howManyTimes === 0) {
   return fnToCallWhenDone();
  }

  // If we haven't returned, then howManyTimes is not
  // zero. Run the real operational code once, and tell
  // to run this control function when its code is done:
  doAsynchronousStuff(function doThisWhenDone() {
    // the "when done with the real code" function simply
    // calls this control function with the "how many times?"
    // value decremented by one. If we had to run 5 times,
    // the next call will tell it to run 4 times, etc.
    runSeveralTimes(fnToCallWhenDone, howManyTimes - 1);
  }, ...);
}

In this code the doAsynchronousStuff function is your actual code.

The use of requestAnimationFrame is to ensure the call doesn't flood the callstack. Since the work is technically independent, we can schedule it to be called "on the next tick" instead.

The call chain is a bit like this:

// let's say we need to run 5 times
runSeveralTimes(5);
=> doAsynchronousStuff()
   => runSeveralTimes(5-1 = 4)
      => this is on a new tick, on a new stack, so
         this actually happens as if a "new" call:
runSeveralTimes(4)
=> doAsynchronousStuff()
   => runSeveralTimes(4-1 = 3), on new stack
runSeveralTimes(3)
...
=> doAsynchronousStuff()
   => runSeveralTimes(1-1 = 0), on new stack
runSeveralTimes(0)
=> fnToCallWhenDone()
=> return
<end of call chain>

Solution 2:

You need to use a while loop and have the loop exit only when all your fetches have completed.

function checkImdb (totalCasts) {
 currentCastId = 1;
 totalCasts = 3;
 doneLoading = false;

 while (!doneLoading)
 { 
       //do something
       currentCastId++;

      if (currentCastId == totalCasts)
           doneLoading = true;
 }
}

Post a Comment for "How To Make A Javascript FOR LOOP Wait For Certain Conditions Before Looping"