如何在循环之前使javascript FOR LOOP等待某些条件

时间:2013-11-01 15:54:00

标签: javascript for-loop callback

我必须调用一个函数(checkImdb),它将从php文件(temp.php)中获取一些信息并将一些内容放在div(placeToFetchTo)上。这必须做一定次数,所以我使用了FOR LOOP。 问题是只使用循环计数器的最后一个实例(currentCastId)。我知道需要有一种方法来强制FOR LOOP等待获取完成,我一直在网上寻找答案,但到目前为止似乎没有任何工作。如果我错过了已经存在的最终答案,我道歉。 任何帮助表示赞赏。 这是我所指的代码:

function checkImdb (totalCasts) {
    $(function() {
        for (currentCastId = 1; currentCastId <= totalCasts; currentCastId++) {
                //Gets cast IMDB#
                var row = document.getElementById("area2-" + currentCastId)
                row = row.innerHTML.toString();
                var fetchThis = "temp.php?id=" + row + "\ .filmo-category-section:first b a";
                placeToFetchTo = "#area0-" + currentCastId;

                function load_complete() {
                    var filhos = $(placeToFetchTo).children().length, newDiv ="";
                    var nrMoviesMissing = 0, looped = 0;
                            alert("done- "+ placeToFetchTo);

                }

                document.getElementById("area0").innerHTML = document.getElementById("area0").innerHTML + "<div id=\"area0-" + currentCastId + "\"></div>";

                $(placeToFetchTo).load(fetchThis, null, load_complete);

        } //End of: for (imdbLooper = 0; imdbLooper <= totalCasts; imdbLooper++) {

    }); //End of: $(function() {
}

2 个答案:

答案 0 :(得分:3)

2017更新:原始答案将回调arg作为函数签名中的最后一个arg。但是,现在ES6扩展运算符是真实的,最好的做法是将它放在第一个,而不是 last ,以便扩展运算符可用于捕获“所有内容其他”。


如果你需要做任何“等待”,你真的不想使用for循环。相反,使用自终止递归:

/**
 * 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);
  }, ...);
}

在此代码中,doAsynchronousStuff函数是您的实际代码。

requestAnimationFrame的使用是为了确保呼叫不会充斥着callstack。由于工作在技术上是独立的,我们可以安排将其称为“在下一个刻度线上”。

调用链有点像这样:

// 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>

答案 1 :(得分:0)

您需要使用while循环,并且仅在所有提取完成后才退出循环。

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

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

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