【问题标题】:Why does jQuery.then() behave differently when using $.deferred and $.ajax为什么使用 $.deferred 和 $.ajax 时 jQuery.then() 的行为不同
【发布时间】:2013-04-01 05:45:06
【问题描述】:

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

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

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

定义完成
然后定义
然后是第二个 ajax 预过滤器
第二个 ajax 完成
然后是第二个 ajax
ajax 完成
然后是ajax

我不明白为什么先执行预过滤步骤。我本来希望它最后被执行,或者根本不执行。

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

// 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 调用中的预过滤函数
done 被称为函数
然后是第二个 ajax 预过滤器
第二个 ajax 完成
然后是第二个 ajax

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

【问题讨论】:

  • 您使用的是同步 jax 吗?否则你应该避免document.write
  • 我最初使用 document.write 创建了一个 jsfiddle 来演示代码,但决定将其改为内联

标签: javascript jquery jquery-deferred


【解决方案1】:

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

我不明白为什么先执行预过滤步骤。我本来希望它最后被执行,或者根本不执行。

回调按照它们添加到延迟对象的顺序执行。并且预过滤器在$.ajax 内部执行,即,甚至在$.ajax 调用返回之前附加回调并且可以附加您的donethen 处理程序。

【讨论】:

  • 您回答的第一部分是我的理解。你回答的第二部分已经回答了我的问题。在看到您的答案之前,我没有意识到 $.ajaxPrefilter() 是在 $.ajax() 方法内执行的。谢谢
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    我不明白为什么先执行预过滤步骤。我本来希望它最后被执行,或者根本不执行。

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

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

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

    【讨论】:

      猜你喜欢
      • 2022-12-03
      • 2015-08-08
      • 1970-01-01
      • 2017-05-19
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 2018-01-19
      • 1970-01-01
      相关资源
      最近更新 更多