AJAX 请求不再指向成功回调方法中的正确变量

AJAX request no longer pointing to correct variable in success callback method

例如,在我的 HTML 文件中,我在 table 中有以下 table 行,其中 {{ }} 只是变量:

<tr id="{{ object.id }}">
    <td class="name">{{ object.name }}</td>
</tr>
<tr id="{{ object.id }}">
    <td class="name">{{ object.name }}</td>
</tr>

然后在我的 JavaScript 文件中有以下代码:

var rows = document.getElementsByTagName("tr"); 

for (var r = 0; r < rows.length; r++){
        var tr = rows[r];
        var id = tr.id;

        $.ajax({
            url: "/some-link/" + id,
            success: function(some_json){
                some_json = JSON.parse(some_json);
                var td = document.createElement("td");
                td.innerHTML = some_json;

                //Problem is the following tr is referring to the last tr in the for loop by the time the AJAX request is complete
                tr.appendChild(td);
            }
        });
    }

我得到的结果是:

<tr id="{{ object.id }}">
    <td class="name">{{ object.name }}</td>
</tr>
<tr id="{{ object.id }}">
    <td class="name">{{ object.name }}</td>
    <td>SomeJSON from when rows was 0 in the for loop</td>
    <td>SomeJSON from when rows was 1 in the for loop</td>
</tr>

然而,我的预期结果是:

<tr id="{{ object.id }}">
    <td class="name">{{ object.name }}</td>
    <td>SomeJSON from when rows was 0 in the for loop</td>
</tr>
<tr id="{{ object.id }}">
    <td class="name">{{ object.name }}</td>
    <td>SomeJSON from when rows was 1 in the for loop</td>
</tr>

我知道我可以通过添加到 AJAX 请求来解决这个问题 async: false 但我想让它保持异步。

任何帮助将不胜感激。

这可能是涉及 Javascript 闭包的问题吗?如果您在 for 循环内定义一个函数并在函数内分配变量,它们将通过成功回调保留其范围。

另一种(cleaner/more 优雅)解决方案会将 for 循环和函数调用重写为 Array.prototype.forEach() (thanks )

We are using [] as a shorthand for accessing the Array prototype, and using .call in order to create the scoped function

在函数内部,变量是有作用域的。以前,每个 ajax 成功回调都引用相同的变量(这是异步请求返回时的变量)

[].forEach.call(rows, function(tr) { 
        var id = tr.id;

        $.ajax({
            url: "/some-link/" + id,
            success: function(some_json){
                some_json = JSON.parse(some_json);
                var td = document.createElement("td");
                td.innerHTML = some_json;

                tr.appendChild(td);
            }
        });

});