为什么使用$ .deferred和$ .ajax时jQuery.then()的行为会有所不同

时间:2013-04-09 16:58:55

标签: javascript jquery jquery-deferred

我一直试图了解jQuery Deferred对象。我的目的是检查每个ajax响应(成功/失败)。我想这样做而不会干扰声明典型的$ .ajax()。done()。fail()请求的其他代码。

我使用$ .ajaxPrefilter()来获取每个ajax请求,然后再执行它。在jqXHR对象上使用.then()方法,我设法添加了一个函数,该函数将在.done()方法放在原始的$ .ajax()调用之前调用

以下代码将打印出以下内容:

  

def done
  def然后
  第二个ajax预滤器然后
  第二次ajax完成了   第二个ajax然后
  ajax完成了   ajax然后

我不明白为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本没有。

行为是我想要的,但我不明白为什么。

// this is a typical usage of deferred with two done functions added, the second via .then()
var def = $.Deferred();
def.done(function(){
    document.write("def done<br>");
});
def.then(function(){
    document.write("def then<br>");
});
def.resolve();

// this is a typical ajax request with a done function added, followed by another using .then()
$.ajax("/echo/json/").done(function(){
    document.write("ajax done<br>");
}).then(function(){
    document.write("ajax then<br>");
});

// for the third request i intercept and call the .then() method 
$.ajaxPrefilter( 
    function( options, originalOptions, jqXHR ) {
                jqXHR.then(function(data, textStatus, jqXHR){
                     document.write("2nd ajax prefilter then<br>");
                    });
            });

// create a typical ajax request. these will be executed after the prefilter .then()
$.ajax("/echo/json/").done(function(){
    document.write("2nd ajax done<br>");
}).then(function(){
    document.write("2nd ajax then<br>");
});

提前感谢您提供任何帮助

更新:------------

从@Bergi响应,下面的代码演示了在done()之前如何调用$ .ajaxPrefilter()。

$.ajaxPrefilter( 
    function( options, originalOptions, jqXHR ) {
            document.write("prefilter function within $.ajax call<br>");
                jqXHR.then(function(data, textStatus, jqXHR){
                     document.write("2nd ajax prefilter then<br>");
                    });
            });

var functionToRunWhenDoneIsCalled = function() {
    document.write("done is called function<br>");
    return function(){
       document.write("2nd ajax done<br>");
    }
}

$.ajax("/echo/json/").done(
    (functionToRunWhenDoneIsCalled)()
).then(function(){
    document.write("2nd ajax then<br>");
});

输出:

  

$ .ajax调用中的prefilter函数
  完成称为功能
  第二个ajax预滤器然后
  第二次ajax完成了   第二个ajax然后

这回答了我关于.then()方法如何在.done()方法之前附加到延迟的jqXHR对象的问题。

3 个答案:

答案 0 :(得分:3)

在您的情况下,使用.done().then()添加回调之间没有区别。仅使用.done()就足够了。

  

我不明白为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本没有。

回调按照添加到延迟对象的顺序执行。 prefilter在$.ajax内部执行,即在$.ajax调用返回之前附加回调,并且可以附加donethen处理程序。

答案 1 :(得分:1)

如果您没有返回延迟对象,则所有.then都会执行另一个已完成的失败和/或进度处理程序添加到延迟对象。考虑到这一点,预先过滤器中添加的.then$.ajax()之后添加之前执行是完全合理的,因为预过滤器回调中的代码首先发生。回调首先在先出后触发。

答案 2 :(得分:1)

  

我不明白为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本没有。

您已将另一个“要做的事情”附加到与ajax请求关联的jqXHR。由于它是 pre -filter,因此在ajax请求使用的标准完成/失败之前附加。处理程序按照它们所附的顺序运行,因此预滤器是第一个。

请注意,由于预过滤器仅在.then()方法中附加了单个函数,因此如果请求因某种原因失败,则不会运行任何操作。听起来你想要第二个(失败处理程序)arg。

至于两个不同的ajax请求的完成顺序,这是不可预测的。它将取决于哪一个首先返回。