2

Please see this code:

for(var k=0;k<pods.length;k++){
        var currentQueryList = new Array();
        currentQueryList[0]=pods[k].queryname;
        console.log("Hello :"+i);
        queryBuilderDWRService.getDataForAllPods(currentQueryList, {callback:function(map){
            podsDataMap = map;
            console.log("Hello"+k+":");
            var pod = pods[k];
            displayPod(k, pod, false);
        }});
    }

In this code, the for loop is completing before the call to queryBuilderDWRService.getDataForAllPods() returns actual data, which I'm using to get data from a database.

It I try console.log("Hello"+i); it is printing Hello :1, Hello :2, Hello :3, Helllo :4, up to array length with no data from DB, meaning that the for loop is completing its execution before than queryBuilderDWRService.getDataForAllPods() returns.

What I need is that, once control is entering in the for loop, it has to complete the execution of queryBuilderDWRService.getDataForAllPods() and only then the next iteration can follow.

Thanks in advance.

4

3 回答 3

5

You can use "asynchronous pseudo-recursion" instead of a for loop, with the general pattern that I use being:

var pods = [ ... ];

(function loop() {
    if (pods.length) {
        var pod = pods.shift();   // take (and remove) first element

        // do something with "pod"
        ...

        // recurse - put this inside a finish callback if "do something" is async
        loop();
     }
})();   // closing braces start invocation immediately

where in your case, the call to loop should be the last thing inside your callback function.


NB: This pattern can also be used to avoid the "browser not responding" error seen with longer running non-async operations by replacing the call to loop() with setTimeout(loop, 0).

This use of setTimeout turns a synchronous recursive function into an asynchronous pseudo-recursive one, in the process avoiding the possibility of any stack overflow errors.

The only downside is the 4ms minimum delay between iterations.

于 2013-07-15T21:29:27.123 回答
0

From the way you have it setup, the call you are making is likely async and therefore the loop will complete execution before the callback to the function you have defined. So it seems you want to build up your currentQueryList array and then make a single call to getDataForAllPods and then, in the callback, finish up the display. What is it that is returned in the map?

于 2013-07-15T21:31:41.920 回答
0

You should use a self executing function, called a closure.

var currentQueryList = [];
for(var i=0,l=pods.length; i<l; i++){
  (function(i){
    currentQueryList[0]=pods[i].queryname;
    console.log('Hello :'+i);
    queryBuilderDWRService.getDataForAllPods(currentQueryList, {callback:function(map){
      podsDataMap = map;
      console.log('Hello'+i+':');
      var pod = pods[i];
      displayPod(i, pod, false);
    }});
  })(i);
}

The problem is, when you call the event, the loop has already run through. Since i is scoped within your loop, when the event fires, it looks for the value of i, which is pods.length-1, since you have used <. You need the scope of your increment to be stored into separate memory spaces, which will be accessed when the event fires.

Note that you have made podsDataMap a global variable, and I changed your code slightly.

于 2013-07-15T21:44:31.503 回答