【问题标题】:jQuery: Why does $.ajax() not wait for request to complete before returning?jQuery:为什么 $.ajax() 在返回之前不等待请求完成?
【发布时间】:2012-06-07 12:59:07
【问题描述】:

我刚刚花了 3 个小时调试了一些代码,结果发现它是由我假设以下代码的执行顺序是线性的:-

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

这不是第一次给我带来问题,我只是想知道这种行为的原因是什么?

这样任何 ajax 请求都不会阻碍其他可能与 ajax 请求无关的脚本执行吗?

【问题讨论】:

  • AJAX 中的第一个A 代表异步。
  • 您可以设置选项async: true。同步请求可能会暂时锁定浏览器,在请求处于活动状态时禁用任何操作。不推荐。
  • @Gareth 我知道 A 代表异步,但是我一直认为这是指在没有“重新加载”页面的情况下发出请求的事实,即发出“父”http请求再次,因此该页面与传递该页面的原始 http 请求“不同步”。
  • +1 这个问题,因为它是关于对一个基本和重要观点的误解,它写得很清楚,并且吸引了一些相当不错(而不是居高临下!)的答案。
  • @rgvcorley 啊。不,正如下面的答案所说,调用是异步的,因此会立即返回。做你需要的两种方法是1)关闭异步(通常是坏主意)或2)在成功时使用回调。

标签: ajax jquery


【解决方案1】:

大多数其他答案都在回答如何处理这个问题。我想非常简要地了解一下为什么在这种情况下异步是好的。

事实上,大多数浏览器内的 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 调用而停止使用该页面。你的用户不在乎。您的用户可能会关心您的正常 onscroll 行为不起作用,因为您的脚本当前与不相关的 AJAX 请求相关联。为了配合整个浏览器 Javascript 编程的异步特性,绝大多数 HTTP 调用应该是非阻塞的、异步的。

【讨论】:

  • 这正是我一直在寻找的答案 - 你是对的我不是在寻找问题的解决方案(我很清楚如何使请求同步)我想知道为什么它是异步的,非常感谢!
【解决方案2】:

因为 ajax 是异步的。如果你想在 ajax 调用成功时执行某些操作,请使用成功事件

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

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

Asynchronous 表示?

异步 ​​I/O 或非阻塞 I/O 是输入/输出的一种形式 允许其他处理在 传输已完成。异步 I/O 用于提高吞吐量、延迟和/或响应能力。

【讨论】:

  • 好的,太好了 - 我知道 A 代表异步,但是我一直认为这是指在没有“重新加载”页面的情况下发出请求(即,使“父' 再次发出 http 请求),因此该页面与传递该页面的原始 http 请求“不同步”。
  • 通常人们使用 ajax 进行部分页面更新而无需重新加载完整的页面(您可能在 facebook、twitter、stackoverflow 等中看到过)以提供良好的用户体验
  • ...但这不是异步所指的
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    要阻止 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');
      }
    });
    

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

          正如其他人所说,ajax 代表 Asynchronous Javascript and Xml。话虽如此,您可以使用jquerys ajax 函数执行以下任一操作:

          1. 如果您希望调用是同步的,请将“async”选项设置为 false。默认情况下是这样。请参阅文档。从 jQuery 1.8 开始,不推荐使用此属性。

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

            请求完成时调用的函数(成功后 错误回调被执行)。

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

            请求成功时调用的函数。

          【讨论】:

          • 我不是在问如何使请求同步 - 我是在问为什么它是异步的
          【解决方案8】:

          AJAX中的第一个A代表Asynchronous;这意味着 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

          【讨论】:

            【解决方案9】:

            另一种选择是简单地将 async 设置为 false

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

            这样你的下一条语句在 $.ajax 语句完成之前不会被执行。

            【讨论】:

              猜你喜欢
              • 2013-09-26
              • 1970-01-01
              • 2020-06-08
              • 2012-07-08
              • 2010-10-19
              • 1970-01-01
              • 2017-03-15
              • 1970-01-01
              • 2014-02-19
              相关资源
              最近更新 更多