延迟对象回调挂钩的JQuery执行顺序(承诺与完成)

时间:2017-06-26 17:08:24

标签: jquery ajax jquery-deferred

我有一个本地托管的项目,其视图向服务器发出AJAX请求。代码在this jsfiddle中重复,没有使用jsfiddle测试数据替换的URL和数据参数来模仿AJAX请求。

(function demo(iteration) {
    count = iteration || 0;

  if (count < 3) {
    $.when(testPromise(count).promise())
        .done(function () {
        doSomething();
        })
      .always(function () {
        demo(count + 1);
        });
  }
})();

function doSomething() {
    console.log("something!");
}

function testPromise(iteration) {
  var deferred = $.ajax({
    type: 'POST',
    url: '/echo/json/',
    data: {
      json: JSON.stringify({ "data": "Data!" }),
      delay: 0.1
    },
    dataType: 'json',
    beforeSend: function () {
            console.log("Before Send: " + iteration);
    },
    success: function(response) {
      console.log("Success: " + iteration);
    },
    error: function() {
        console.log("Error: " + iteration);
    },
    complete: function () {
        console.log("Complete: " + iteration);
    }
  });

  return deferred;
}

现在,Jsfiddle生成以下打印语句:

jsfiddle output

但是,我的本地代码会生成另一组打印语句:

local output

您会注意到jsfiddle连续的AJAX请求按顺序发出并完成,但是本地输出显示在前一个请求完成之前发出连续请求:发送前:1;完成:0 发送前:2;完成:1 。也就是说,对于这两种环境,Promise回调和完成回调的处理顺序不同。

根据http://api.jquery.com/jquery.ajax/

  

$ .ajax()提供的回调挂钩如下:

     
      
  1. 调用beforeSend回调选项。
  2.   
  3. 错误......
  4.   
  5. dataFilter ...
  6.   如果请求成功,则调用
  7. 成功回调选项。
  8.   
  9. 承诺回调 - .done(),. fail(),. aways()和.then() - 按照它们的注册顺序被调用。
  10.   
  11. 完成回调选项会在请求完成时触发,无论是失败还是成功。
  12.   

除了列表顺序之外,文档并没有真正指出这些回调的顺序是否得到保证,并且我认为实际上无法保证顺序,因为jsfiddle和我的本地代码不协调。

那么,为了产生这两种不同的结果,发生了什么?并且假设我希望我的本地代码表现得像jsfiddle(在Promise之前完成处理) - 我可以做些什么改变来完成这个?

提前致谢 -

作为旁注,我知道可以通过AJAX .complete()处理程序实现以下$ .when()功能。我故意使AJAX函数与它需要被调用的条件无关,因为我的最终目标是创建一个通用队列模块,它将处理队列处理并根据需要调用给定的可延迟函数。因此,我没有为此目的使用AJAX .complete()方法。

$.when(testPromise(count).promise())
    .done(function () {
        doSomething();
    })
    .always(function () {
        demo(count + 1);
    });

1 个答案:

答案 0 :(得分:1)

jQuery Deferred在版本3.0(https://blog.jquery.com/2016/06/09/jquery-3-0-final-released/)中更新,因此确保您的jQuery版本与小提琴(3.2.1)相同可能会有所帮助。