By n4rzul


2011-02-21 12:35:58 8 Comments

I know this question has been asked countless times, but I cant figure out for the life of me how to make this answer work in my case: wait for async javascript function to return

I'm looping through some "tv channels" in the outerloop and then looping through dates in the week in the innerloop. In the inner loop I make a ajax request to a server to fetch the data and I then store/cache it for later use like so

var dates = []; //<-- Contains a list of dates for the coming week 
var baseUrl = "http://www.someserver.com";
var storedChannels = [1,2,3,4,5,6,7,8,9,10,45,23,56,34,23,67,23,567,234,67,345,465,67,34];

for(ch = 0; ch < storedChannels.length; ch++) {   
    var channel = storedChannels[ch];
    for(d=0; d < 7; d++) {
        var currentDate = dates[d];
        ajax({    
            url: baseUrl+"?ch="+channel+"&dt=currentDate"+,
            complete: function(res) {
                CMLocalStore.setString('ch' + ch + "_" + scheduleDay, res);
            },
        });
        //Want to wait here till the ajax request completes.
        //Do not want to continue to next iteration.
        //Do not want to fire of 50 bazillion ajax requests all at once
        //Why? Very limited bandwidth scenario, plenty of channels  
    }
}

PS: NO JQuery please! Plain JS solutions only

Many thanks!

5 comments

@n4rzul 2011-02-23 13:34:38

Essentially the answer lies in using recursive calls instead of using loops. Just wanted to add this answer for anyone that might be interested in "for loop nestings" deeper than 2 levels. As you can see its easy to extend to as many "nestings" as you like. Original credit goes to VatooVatoo implementation in Java on the DaniWeb forums.

Heres the code, tested and works (without the ajax bits of course but you can add that yourself):

<html>
<head>
<script type="text/javascript">
    function loopRecurse(a, b, c)
    {
        if(c >= 2) {
            b++;
            c=0;
            loopRecurse(a, b, c);
            return;
        }
        if(b >= 2) {
            a++;
            b=0;
            loopRecurse(a, b, c);
            return;
        }
        if(a >= 2) return;
        document.write("<div>" + a + "|" + b + "|" + c + "</div>");
        c++;
        loopRecurse(a, b, c);
    }
    loopRecurse(0, 0, 0);
</script>
</head>
<body>
    <!-- output
        0|0|0
        0|0|1
        0|1|0
        0|1|1
        1|0|0
        1|0|1
        1|1|0
        1|1|1
     -->
</body>
</html>

@rsp 2011-02-21 12:55:07

What you are trying to do is explained in the Asynchronous Iteration Patterns tutorial by Pedro Teixeira. The examples are using Node.js but you can use the same patterns in the browser. Basically what you need to do is convert your loops to serial callbacks waiting on each other to complete, so the next AJAX request is fired from the success callback of the previous one etc. It can be done without blocking the browser but not in loops. See that tutorial.

@andynormancx 2011-02-21 12:45:30

You want something like this. I haven't tested it, but hopefully you should get the idea.

var dates = []; //<-- Contains a list of dates for the coming week 
var baseUrl = "http://www.someserver.com";
var storedChannels = [1,2,3,4,5,6,7,8,9,10,45,23,56,34,23,67,23,567,234,67,345,465,67,34];

function ProcessNext(ch, d) {
    if (d < 7) {
        d++;
    } else {
        d=0;
        if (ch < storedChannels.length) {
            ch++;
        } else {
            return;
        }
    }

    var channel = storedChannels[ch];
    var currentDate = dates[d];
    ajax({    
        url: baseUrl+"?ch="+channel+"&dt=currentDate"+,
        complete: function(res) {
            CMLocalStore.setString('ch' + ch + "_" + scheduleDay, res);
            ProcessNext(ch, d);
            },
    });
}

ProcessNext(0, 0);

@n4rzul 2011-02-21 13:03:16

Oooooo, aaaa, a solution that actually doesn't block execution, I like. Let me check out this too.

@n4rzul 2011-02-22 07:44:26

Thanks Andy. In the end this achieves exactly what I want without locking up the browser. The code above is not 100% so had to make a few changes, but the concept is spot on.

@Shadikka 2011-02-21 12:41:07

See the XMLHttpRequest documentation (linked to MDC, but shouldn't matter). Basically the condition you're looking for is request.readyState==4 - presuming that you have your ajax() return the actual XMLHttpRequest object.

@SLaks 2011-02-21 12:40:30

You need to turn your loop into a chain of callbacks.

Instead of using a loop, you should make your callback call your original function, but with a higher parameter value.

@andynormancx 2011-02-22 07:43:46

See my answer for a practical implementation of this stackoverflow.com/questions/5066002/…

Related Questions

Sponsored Content

93 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 6241619 View
  • 7792 Score
  • 93 Answer
  • Tags:   javascript arrays

43 Answered Questions

[SOLVED] Loop through an array in JavaScript

42 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

39 Answered Questions

[SOLVED] How do I loop through or enumerate a JavaScript object?

32 Answered Questions

[SOLVED] How to manage a redirect request after a jQuery Ajax call

36 Answered Questions

[SOLVED] How do I return the response from an asynchronous call?

44 Answered Questions

[SOLVED] JavaScript closure inside loops – simple practical example

21 Answered Questions

[SOLVED] How to loop through a plain JavaScript object with the objects as members?

  • 2009-05-28 16:18:14
  • edt
  • 1606249 View
  • 1548 Score
  • 21 Answer
  • Tags:   javascript

17 Answered Questions

[SOLVED] Abort Ajax requests using jQuery

Sponsored Content