使用异步 jQuery 请求时出现意外结果
Unexpected results when using asynchronous jQuery request
在我的网站上,我有一个 table 和一些“添加”link。通过点击添加 links,一个 ajax 请求被触发,并且 - 一旦这个请求被执行 - 一个新的 table 行直接在“添加”link 行已创建。
当一次只点击一个“添加”link 时,脚本按预期工作。
但是get请求调用的脚本执行时间大约为2秒。所以它可能会发生,请求 运行 parallel.
如果我在第一个仍在加载时单击第二个“添加”link,则两个新行都会添加到第二个 table 行下方。
另一方面,当单击第一个“添加”link 而第二个仍在加载时,两个新行都会添加到第一个 table 行下方。 (所以在两者之间添加 links)。
这不是我想要的行为:我预计,当同时单击“添加”link时,我会在每一行之后得到一个新行。
我想这可能会发生,因为加载第二个响应时变量“click”被覆盖,而第一个响应仍然是 运行ning?我怎样才能防止这种行为?
$('a.open').bind('click', function () {
id=$(this).attr('id');
click=$(this);
$.get("#", {key:id})
.done(function( data ) {
text=data.html;
click.closest('tr').after('<tr><td></td><td>'+text+'</td></tr>');
})
.fail(function (jqXHR, textStatus) {
click.closest('tr').after('<tr><td></td><td>error</td></tr>');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border=1>
<tr>
<td><a href="#" id="12333" class="open">add</a></td>
<td>some text</td>
</tr>
<tr>
<td><a href="#" id="23457" class="open">add</a></td>
<td>some other text</td>
</tr>
</table>
问题确实是 id
和 click
值在 AJAX 调用完成之前被覆盖。
发生这种情况是因为您没有使用变量关键字,例如 var
、let
或 const
来声明您的变量。因此 id
和 click
将作为属性分配给 window
对象。您可以通过在函数中记录 window.id
来测试它。
$('a.open').on('click', function() {
id = $(this).attr('id');
console.log(window.id);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border=1>
<tr>
<td><a href="#" id="12333" class="open">add</a></td>
<td>some text</td>
</tr>
<tr>
<td><a href="#" id="23457" class="open">add</a></td>
<td>some other text</td>
</tr>
</table>
您可以使用 const
or let
解决此问题。两者都是 block-scoped 局部变量,这意味着它们仅存在于它们所在的范围内。在这种情况下,它们仅存在于处理您的点击事件的 function() { ... }
中。
var
也可以,但我建议查看前两个,因为它们允许更多地控制范围。
$('a.open').on('click', function() {
const id = $(this).attr('id');
const click = $(this);
setTimeout(function() {
click.closest('tr').after('<tr><td></td><td>Foobar</td></tr>');
}, 3000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border=1>
<tr>
<td><a href="#" id="12333" class="open">add</a></td>
<td>some text</td>
</tr>
<tr>
<td><a href="#" id="23457" class="open">add</a></td>
<td>some other text</td>
</tr>
</table>
在我的网站上,我有一个 table 和一些“添加”link。通过点击添加 links,一个 ajax 请求被触发,并且 - 一旦这个请求被执行 - 一个新的 table 行直接在“添加”link 行已创建。
当一次只点击一个“添加”link 时,脚本按预期工作。
但是get请求调用的脚本执行时间大约为2秒。所以它可能会发生,请求 运行 parallel.
如果我在第一个仍在加载时单击第二个“添加”link,则两个新行都会添加到第二个 table 行下方。 另一方面,当单击第一个“添加”link 而第二个仍在加载时,两个新行都会添加到第一个 table 行下方。 (所以在两者之间添加 links)。
这不是我想要的行为:我预计,当同时单击“添加”link时,我会在每一行之后得到一个新行。
我想这可能会发生,因为加载第二个响应时变量“click”被覆盖,而第一个响应仍然是 运行ning?我怎样才能防止这种行为?
$('a.open').bind('click', function () {
id=$(this).attr('id');
click=$(this);
$.get("#", {key:id})
.done(function( data ) {
text=data.html;
click.closest('tr').after('<tr><td></td><td>'+text+'</td></tr>');
})
.fail(function (jqXHR, textStatus) {
click.closest('tr').after('<tr><td></td><td>error</td></tr>');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border=1>
<tr>
<td><a href="#" id="12333" class="open">add</a></td>
<td>some text</td>
</tr>
<tr>
<td><a href="#" id="23457" class="open">add</a></td>
<td>some other text</td>
</tr>
</table>
问题确实是 id
和 click
值在 AJAX 调用完成之前被覆盖。
发生这种情况是因为您没有使用变量关键字,例如 var
、let
或 const
来声明您的变量。因此 id
和 click
将作为属性分配给 window
对象。您可以通过在函数中记录 window.id
来测试它。
$('a.open').on('click', function() {
id = $(this).attr('id');
console.log(window.id);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border=1>
<tr>
<td><a href="#" id="12333" class="open">add</a></td>
<td>some text</td>
</tr>
<tr>
<td><a href="#" id="23457" class="open">add</a></td>
<td>some other text</td>
</tr>
</table>
您可以使用 const
or let
解决此问题。两者都是 block-scoped 局部变量,这意味着它们仅存在于它们所在的范围内。在这种情况下,它们仅存在于处理您的点击事件的 function() { ... }
中。
var
也可以,但我建议查看前两个,因为它们允许更多地控制范围。
$('a.open').on('click', function() {
const id = $(this).attr('id');
const click = $(this);
setTimeout(function() {
click.closest('tr').after('<tr><td></td><td>Foobar</td></tr>');
}, 3000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border=1>
<tr>
<td><a href="#" id="12333" class="open">add</a></td>
<td>some text</td>
</tr>
<tr>
<td><a href="#" id="23457" class="open">add</a></td>
<td>some other text</td>
</tr>
</table>