jQuery:为什么$.ajax()在返回之前不等待请求完成?

13

我刚刚花了三个小时调试一段代码,最后发现是因为我错误地假设以下代码执行的顺序是线性的:

$.ajax( {ajax options} );
console.log('I was assuming this would execute once the ajax request was complete');

这不是我第一次遇到这个问题了,我想知道这种行为的原因是什么?

是因为任何ajax请求都不会阻塞其他与ajax请求无关的脚本执行吗?


18
AJAX 中的第一个字母 A 代表异步。 - Gareth
3
你可以设置选项async:true。同步请求可能会暂时锁定浏览器,禁止任何操作,直到请求结束。不建议使用。 - jasssonpet
@Gareth 我知道 A 代表异步,但我一直认为这是指请求是在不重新加载页面的情况下进行的,即不再次进行“父”http请求,因此页面与交付页面的原始http请求“不同步”。 - rgvcorley
8
这个问题很好,因为它涉及一个基本而重要的观点的误解,写得非常清楚,并吸引了一些相当不错(而且不傲慢!)的回答。+1 - Tom Anderson
@rgvcorley 啊。不,正如下面的答案所说,调用是异步的,因此会立即返回。实现您所需的两种方法是:1)关闭异步(通常不是好主意),或者2)在成功时使用回调函数。 - Gareth
@Gareth 真是疯了 - 实际上有成千上万的人误解了 ajax 中异步的含义 - 我已经读了很多文章(甚至在书中也看到过!),认为异步是因为页面不重新加载! - rgvcorley
9个回答

12

大多数其他答案都是回答如何处理这个问题。我想简单地探讨一下为什么在这种情况下异步操作是好的。

实际上,大多数浏览器中的JavaScript都是异步的。例如,看看这段代码:

document.getElementById('foo').onclick = function() {
    alert('foo clicked');
};
document.getElementById('bar').onclick = function() {
    alert('bar clicked');
};

哪个会先运行?你不知道,因为浏览器模型(或事实上大多数事件驱动代码)具有异步性。当发生事件时,您运行代码。您设置文档,然后等待事件发生,您的代码可能以各种不同的顺序执行,这取决于哪些事件首先发生。Javascript代码需要在页面的整个生命周期中执行,而不仅仅是在创建页面时。

所以,一般来说 Javascript编程(或者至少是超出最简单水平的Javascript编程)通常是异步的。此外,让HTTP请求异步化也是非常有意义的。

首先,正如您在问题中暗示的那样,使代码同步化将阻止执行。也就是说,您可能不希望由于两行代码之间进行了一个HTTP请求而使动画等待两秒钟才开始。服务器响应时间可能是(a)不规则的和(b)缓慢的,因此,将您的应用程序的设计依赖于服务器响应速度是没有意义的。

其次,更重要的是,您的用户不会因为您的脚本正在进行AJAX调用而停止使用页面。您的用户不关心。您的用户可能会关心,因为您的脚本目前正在处理不相关的AJAX请求,导致您的正常onscroll行为不起作用。为配合整个浏览器Javascript编程的异步性质,绝大多数HTTP调用应该是非阻塞的、异步的。


这正是我在寻找的答案 - 你说得对,我并不是在寻找解决问题的方法(我很清楚如何使请求同步),我想知道为什么它是异步的,非常感谢你! - rgvcorley

10

ajax是异步的,如果你希望在ajax调用成功后执行某些操作,请使用success事件。

$.ajax({
  url: 'yourserverpage.php',
  success: function(data) {

    alert('This will be executed only when ajax call is success /finished');
  }
});

异步的意思是什么?

异步I/O或非阻塞I/O是一种输入/输出处理形式,允许传输完成之前其他处理继续进行。异步I/O用于提高吞吐量、延迟和/或响应能力。


好的,太棒了 - 我知道A代表异步,但我一直认为这是指请求是在不重新加载页面的情况下进行的(即不再次发出“父”HTTP请求),因此页面与提供页面的原始HTTP请求“不同步”。 - rgvcorley
通常人们使用Ajax进行部分页面更新而无需完全重新加载页面(您可能在Facebook、Twitter、StackOverflow等网站上看到过),以提供良好的用户体验。 - Shyju
...但这不是异步正在引用的意思 - rgvcorley

2

jQuery $.ajax() 提供了4个(事件)选项:beforeSend、success、error和complete。在您的情况下,我认为complete是正确的答案。

例如:

$.ajax({
  url: someUrl,
  //...
  beforeSend: function(){
    console.log("I'm sending AJAX.");
    //display loading?
  },
  success: function(data){
    console.log('response: '+data);
  },
  error: function(er){
    console.log(er.responseText);
  },
  complete: function(){
    console.log("I'm done.");
    //hide loading?
  }
});

1
为了防止 AJAX 完成之前,您需要将代码放在 success: 函数中,如下所示:
$.ajax({
  url: 'ajax/test.html',
  success: function(data) {
    // Do something after AJAX is completed.
    console.log('I was assuming this would execute once the ajax request was complete');
  }
});

1

你可以成功完成,或者也可以使用 .done();

$.ajax( {ajax options} ).done(console.log('I was assuming this would execute once the ajax request was complete'));  

0

另一个选项是将async设置为false

$.ajax({
  async : 'false',
  other options
});

通过这种方式,直到$.ajax语句执行完成之前,您的下一条语句将不会被执行。


0

$.ajax 是一个异步函数,因此在返回之前不会等待请求完成。相反,当请求结束时,它会调用您通过 success 和/或 error 指定的回调函数。

如果您确实需要同步行为,可以将选项 async 设置为 false(请参见 docu)。但是,在这种情况下,请注意,整个 UI 将冻结,直到请求完成!


0

正如其他人所说,ajax代表异步JavaScript和XML。 话虽如此,您可以使用{{link1:jquerys ajax}}函数执行以下任一操作:

  1. 如果要使调用同步,则将“async”选项设置为false。 默认情况下为true。 请参阅文档。 自jQuery 1.8以来,不建议使用此属性。

  2. 提供“complete”回调。 默认情况下,这将异步发生。 这是:

    请求完成后(在成功和错误回调之后)要调用的函数。

  3. 提供“success”回调。 默认情况下,这将异步发生。 这是:

    如果请求成功,则要调用的函数。


我不是在问如何使请求同步 - 我在问为什么它是异步的。 - rgvcorley

0

AJAX中的第一个A代表异步;这意味着AJAX调用在后台执行,不会阻塞脚本的执行直到它们完成。这基本上是按设计来实现的。

如果你想在调用完成时运行一些代码,可以在以下一个或多个参数中传递一个函数:

$.ajax({
  // your other options

  done: function(data, textStatus, jqXHR) {
    alert('Success! I got the following data back: ' + data);
    // this runs when the request has finished successfully
  },

  fail: function(jqXHR, textStatus, errorThrown) {
    alert('Oops, there was an error :(');
    // this runs when the request has finished, but with an error
  },

  always: function(jqXHR, textStatus) {
    alert("OK, I'm done.");
    // this runs when the call is finished, regardless
    // of whether it has succeeded or not
  }

更多信息,请查看API:http://api.jquery.com/jQuery.ajax


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接