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

时间:2017-02-25 00:18:01

标签: javascript html ajax flask

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

<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来解决这个问题,但我想让它保持异步。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

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

备用(更干净/更优雅)的解决方案会将for循环和函数调用重写为Array.prototype.forEach()(感谢Jaromanda X

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);
            }
        });

});