19

This js loop script always get the last value of ui_item inside a jquery ajax funciton. How can a catch the correct value of each iteration?

for (var i = 0; i <= split_files_cb_value_holder.length - 1; i++){
    var split_values = split_files_cb_value_holder[i].split(':');

    ui_item = split_files_cb_value_holder[i];

    $.ajax({
        type: "POST",
        url: "ds/index.php/playlist/check_folder",
        data: "component_type="+$('#component_type').val()+"&value="+split_values[1],
        success: function(msg)
        {
            console.log(ui_item); //ALWAYS GETS THE LAST VALUE
        },
        error: function()
        {
            alert("An error occured while updating. Try again in a while");
        }
    });

}

Thanks!

steamboy
  • 1,162
  • 5
  • 20
  • 37
  • 2
    Add `let` before ui_item will solve this. – kamushin Oct 25 '16 at 02:43
  • Possible duplicate of [Calling an asynchronous function within a for loop in JavaScript](https://stackoverflow.com/questions/13343340/calling-an-asynchronous-function-within-a-for-loop-in-javascript) – Liam Oct 01 '19 at 14:21

2 Answers2

48

The problem is that the anonymous callback method captures the ui_item variable by reference. Since there is only one variable, it always gets whatever was assigned last to the variable.

You need to wrap the contents of the for loop in a function that takes i as a parameter, then call the function in the loop. Each call to the wrapper function will create a separate variable, solving the problem.

For example:

function doCheck(i) {
    var split_values = split_files_cb_value_holder[i].split(':');

    var ui_item = split_files_cb_value_holder[i];

    $.ajax({
        type: "POST",
        url: "ds/index.php/playlist/check_folder",
        data: "component_type="+$('#component_type').val()+"&value="+split_values[1],
        success: function(msg)
        {
            console.log(ui_item); //Don't always get the last value
        },
        error: function()
        {
            alert("An error occured while updating. Try again in a while");
        }
    });
}

for (var i = 0; i < split_files_cb_value_holder.length; i++) 
    doCheck(i);
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 3
    Thank you for the correction, but I feel compelled to add a small note. Sometimes tone isn't conveyed well over the internet, and to get a terse comment beginning with "*WRONG*" seemed harsh. But, I was glad to see your answer and appreciated the correction. +1 from me. – awgy Apr 22 '10 at 02:30
  • 4
    @awgy: I'm sorry; I didn't mean to be offensive. However, seeing two identically wrong answers (and one from a >100K user), I wanted to firmly head off the misconception. (And, I'm exhausted) – SLaks Apr 22 '10 at 02:34
  • Can this work with an inline function (i.e. don't give a name to the helper function `doCheck()`). Colocated code has its advantages. – Sridhar Sarnobat Jun 03 '18 at 03:43
-6

Turn async off, it will fix the problem i guess. I mean add this: async:false