How to stop for loop execution untill DWR method execution completion which is inside the for loop

StackOverflow https://stackoverflow.com/questions/17664214

  •  03-06-2022
  •  | 
  •  

Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top