João Gomes
João Gomes

Reputation: 340

Delay in for loop breaks function

I need to create a small delay in this for loop:

for (i = 1; i <= cloneIndex; i++) {
                        var myElem = document.getElementById('form' + i);
                        if (myElem != null) {
                            function postData() {
                                return {
                                udd: document.getElementById('udd').value,
                                data: date_in,
                                hora_ini: hour_in,
                                hora_fim: hour_out,
                                cat: $('#form' + i).find('select[id="cat"]').val(),
                                m1: $('#form' + i).find('select[id="q1"]').val(),
                                m2: $('#form' + i).find('select[id="q2"]').val(),
                                m3: $('#form' + i).find('select[id="q3"]').val(),
                                m4: $('#form' + i).find('select[id="q4"]').val(),
                                m5: $('#form' + i).find('select[id="q5"]').val()
                                }
                            }

                            var newItem = postData();
                            $2sxc(@Dnn.Module.ModuleID).webApi.post('app/auto/content/audits', {}, newItem);
                        }
            }

Following stackoverflow examples, I tried this solution:

for (i = 1; i <= cloneIndex; i++) {
                (function(i){
                    setTimeout(function(){
                        var myElem = document.getElementById('form' + i);
                        if (myElem != null) {
                            function postData() {
                                return {
                                udd: document.getElementById('udd').value,
                                data: date_in,
                                hora_ini: hour_in,
                                hora_fim: hour_out,
                                cat: $('#form' + i).find('select[id="cat"]').val(),
                                m1: $('#form' + i).find('select[id="q1"]').val(),
                                m2: $('#form' + i).find('select[id="q2"]').val(),
                                m3: $('#form' + i).find('select[id="q3"]').val(),
                                m4: $('#form' + i).find('select[id="q4"]').val(),
                                m5: $('#form' + i).find('select[id="q5"]').val()
                                }
                            }

                            var newItem = postData();
                            $2sxc(Dnn.Module.ModuleID).webApi.post('app/auto/content/audits', {}, newItem);
                        }
                    }, 1000 * i);
                }(i));
            }

However this breaks the function inside. It seems myElem is now always null. Too many "i"s? How can I fix this?

Upvotes: 0

Views: 80

Answers (2)

Daniel Beck
Daniel Beck

Reputation: 21475

You need to define the variable inside the closure for it to be unique to each iteration:

for (var i = 1; i < 10; i++) {
  (function() {
    var k = i; // <-- k will be different for each iteration, because it was declared inside the closure. i was defined outside the closure.
    setTimeout(function() {
      console.log("Delayed: ", i, k)
    }, i * 1000)
  }());
}

...or else include i in the closure definition:

for (var i = 1; i < 10; i++) {
  (function(i) {
    setTimeout(function() {
      console.log("Delayed: ", i)
    }, i * 1000)
  }(i));
}

Upvotes: 1

Jo&#227;o Gomes
Jo&#227;o Gomes

Reputation: 340

Nevermind. The reason the code did not work was simple. The rest of the code below did not wait for the delayed loop to end, so it actually broke the function.

This fixed it (placed inside the setTimeout function):

k++;
if (k == cloneIndex) {rest of the code that needs the loop to end}

Upvotes: 0

Related Questions