简体   繁体   中英

Nested for loop incrementation producing inconsistent result

I'm trying to use the variable of the current iteration of the loop in the nested loop.

However when I execute the following code the loop incorrectly starts at f = 6, and then it correctly iterates over the nested loop.

I've removed all the other code and then it works normally. However I have no clue what could possibly be interfering with the loop. There probably is a reason for it and I wish you guys could help me figure this out - and probably learn something more about why this behaviour occurs the way it does.

for (var f = 0; f < 6; f++) {

  var JSONURL = "http://blabla.com/json";

  $.ajax( JSONURL, {
    dataType: "json"
  })
    .done(function(json) {

        for (var i = 0; i < json.timeslots.length; i++) { 

            var StartHour = json.timeslots[i].begintijd.split(":")[0];
            var StartMinute = json.timeslots[i].begintijd.split(":")[1];
            var EndHour = json.timeslots[i].eindtijd.split(":")[0];
            var EndMinute = json.timeslots[i].eindtijd.split(":")[1];

            //Calculate top distance of block in pixels
            if (StartHour < 20) {
                var TopDistance = ((parseInt(StartHour) - 9) * 240) + (parseInt(StartMinute) * 4);

            }

            //Calculate height of block in pixels
            var BlockHeight = ((((parseInt(EndHour) * 60) + (parseInt(EndMinute))) - ((parseInt(StartHour) * 60) + (parseInt(StartMinute)))) * 4) - 2.5;

            //Generate HTML for blocks

            var html_first = '<div data-ix="show-pop-up" class="w-clearfix time-block event-block" style="height:'+BlockHeight+'px; top:'+TopDistance+'px; background-color:'+json.timeslots[i].achtergrondkleur+';">';
            if (json.timeslots[i].afbeelding.length > 0) {
                var html_mid = '<div class="avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div>';
            }
            else {
                html_mid = "";
            }
            var html_last = '<h4 class="card-title">'+json.timeslots[i].naam+'</h4><div class="time-indication">'+json.timeslots[i].begintijd+'</div><div class="speaker-description">'+json.timeslots[i].functie+'</div><div class="hidden-content"><div class="pop-up-wrapper" style="background-color:'+json.timeslots[i].achtergrondkleur+';"><div class="w-clearfix pop-up-header-background"><div data-ix="hide-pop-up" class="close-icon" id="PopupClose"></div><h3 class="white pop-up-title">'+json.timeslots[i].naam+'</h3><div class="pop-up-subtitle">'+json.timeslots[i].functie+'</div></div><div class="w-clearfix pop-up-body"><div class="pop-up-avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div><div class="w-clearfix"><div class="pop-up-card-detail-wrap"><div class="time-label">Begint om</div><div class="pop-up-time-text">'+json.timeslots[i].begintijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">Eindigt om</div><div class="pop-up-time-text">'+json.timeslots[i].eindtijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">plek</div><div class="pop-up-time-text">Zaal 1</div></div></div><p class="pop-up-paragraph">'+json.timeslots[i].beschrijving_lang+'</p></div><div class="pop-up-footer"><a href="'+json.timeslots[i].leesmeer_url+'" class="w-button paragraph-button">Meer over deze spreker</a></div></div></div></div>';

            var html = html_first+html_mid+html_last;
            var TargetDiv = "#Locatie"+f+"Column";

            alert("Parent loop increment: "+f);
            alert("Child loop increment: "+i);
            $(TargetDiv).append(html);
        }
    });
}

It starts at f = 6 because your callback doesn't get called until after f equals 6

What you may do is something to the effect of:

for (var f = 0; f < 6; f++) {

  var JSONURL = "http://blabla.com/json";

  $.ajax( JSONURL, {
    dataType: "json"
  })
    .done(handleResponse.bind(null, f));
}

function handleResponse(f, json) {
    for (var i = 0; i < json.timeslots.length; i++) { 

        var StartHour = json.timeslots[i].begintijd.split(":")[0];
        var StartMinute = json.timeslots[i].begintijd.split(":")[1];
        var EndHour = json.timeslots[i].eindtijd.split(":")[0];
        var EndMinute = json.timeslots[i].eindtijd.split(":")[1];

        //Calculate top distance of block in pixels
        if (StartHour < 20) {
            var TopDistance = ((parseInt(StartHour) - 9) * 240) + (parseInt(StartMinute) * 4);

        }

        //Calculate height of block in pixels
        var BlockHeight = ((((parseInt(EndHour) * 60) + (parseInt(EndMinute))) - ((parseInt(StartHour) * 60) + (parseInt(StartMinute)))) * 4) - 2.5;

        //Generate HTML for blocks

        var html_first = '<div data-ix="show-pop-up" class="w-clearfix time-block event-block" style="height:'+BlockHeight+'px; top:'+TopDistance+'px; background-color:'+json.timeslots[i].achtergrondkleur+';">';
        if (json.timeslots[i].afbeelding.length > 0) {
            var html_mid = '<div class="avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div>';
        }
        else {
            html_mid = "";
        }
        var html_last = '<h4 class="card-title">'+json.timeslots[i].naam+'</h4><div class="time-indication">'+json.timeslots[i].begintijd+'</div><div class="speaker-description">'+json.timeslots[i].functie+'</div><div class="hidden-content"><div class="pop-up-wrapper" style="background-color:'+json.timeslots[i].achtergrondkleur+';"><div class="w-clearfix pop-up-header-background"><div data-ix="hide-pop-up" class="close-icon" id="PopupClose"></div><h3 class="white pop-up-title">'+json.timeslots[i].naam+'</h3><div class="pop-up-subtitle">'+json.timeslots[i].functie+'</div></div><div class="w-clearfix pop-up-body"><div class="pop-up-avatar" style="background-image:url('+json.timeslots[i].afbeelding+');"></div><div class="w-clearfix"><div class="pop-up-card-detail-wrap"><div class="time-label">Begint om</div><div class="pop-up-time-text">'+json.timeslots[i].begintijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">Eindigt om</div><div class="pop-up-time-text">'+json.timeslots[i].eindtijd+'</div></div><div class="pop-up-card-detail-wrap"><div class="time-label">plek</div><div class="pop-up-time-text">Zaal 1</div></div></div><p class="pop-up-paragraph">'+json.timeslots[i].beschrijving_lang+'</p></div><div class="pop-up-footer"><a href="'+json.timeslots[i].leesmeer_url+'" class="w-button paragraph-button">Meer over deze spreker</a></div></div></div></div>';

        var html = html_first+html_mid+html_last;
        var TargetDiv = "#Locatie"+f+"Column";

        alert("Parent loop increment: "+f);
        alert("Child loop increment: "+i);
        $(TargetDiv).append(html);
    }
}

What this does is call handleResponse by passing in the value of f at the time that the loop is run.

The problem is not the nested loop, but the asynchronous call inside the loop. To resolve this issue you can use an immediately-invoked-anonymous-function to pass the correct value to your function, like so :

for (var f = 0; f < 6; f++) {
    (function(foo) {
       //ajax call
       //your ajax call will now have the correct number
    })(f);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM