使用异步 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>

问题确实是 idclick 值在 AJAX 调用完成之前被覆盖。

发生这种情况是因为您没有使用变量关键字,例如 varletconst 来声明您的变量。因此 idclick 将作为属性分配给 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>