简体   繁体   English

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

[英]Why does jQuery.then() behave differently when using $.deferred and $.ajax

I've been trying to get my head around the jQuery Deferred object. 我一直试图绕过jQuery Deferred对象。 My intention is to inspect each ajax response (success/fail). 我的目的是检查每个ajax响应(成功/失败)。 I want to do this without interfering with other code that declares a typical $.ajax().done().fail() request. 我想做到这一点而不会干扰其他声明典型$ .ajax()。done()。fail()请求的代码。

I've user the $.ajaxPrefilter() to get each ajax request before it is executed. 我已经使用$ .ajaxPrefilter()来获取每个ajax请求,然后再执行它。 Using the .then() method on the jqXHR object, I've managed to add a function that will be called before the .done() method placed on the original $.ajax() call 使用jqXHR对象上的.then()方法,我设法添加了一个函数,该函数将在放置在原始$ .ajax()调用上的.done()方法之前被调用。

The code below will print out the following: 下面的代码将打印出以下内容:

def done def完成
def then 然后定义
2nd ajax prefilter then 然后第二个ajax预过滤器
2nd ajax done 第二个ajax完成
2nd ajax then 然后第二个ajax
ajax done 阿贾克斯完成
ajax then 然后阿贾克斯

What I don't understand is why the prefilter step executes first. 我不明白的是为什么要先执行预过滤器步骤。 I would have expected it to have been executed last, or not at all. 我希望它最后执行一次,或者根本不执行。

The behaviour is what I want, but I don't understand why. 这是我想要的行为,但是我不明白为什么。

// 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>");
});

Thanks in advance for any help 预先感谢您的任何帮助

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

From @Bergi response, the code below demonstrates how the $.ajaxPrefilter() is called before the done(). 在@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>");
});

This outputs: 输出:

prefilter function within $.ajax call $ .ajax调用中的预过滤器功能
done is called function 完成称为功能
2nd ajax prefilter then 然后第二个ajax预过滤器
2nd ajax done 第二个ajax完成
2nd ajax then 然后第二个ajax

Which answers my question about how the .then() method is attached to the deferred jqXHR object before the .done() method. 这回答了我关于.then()方法如何在.done()方法之前附加到延迟的jqXHR对象的问题。

In your case, there is no difference between adding callbacks with .done() or with .then() . 在你的情况下,与添加回调之间没有区别.done()或用.then() Using only .done() would be enough. 仅使用.done()就足够了。

What I don't understand is why the prefilter step executes first. 我不明白的是为什么要先执行预过滤器步骤。 I would have expected it to have been executed last, or not at all. 我希望它最后执行一次,或者根本不执行。

Callbacks are executed in the order they are added to the deferred object. 回调将按添加到延迟对象中的顺序执行。 And the prefilter is executed inside of $.ajax , ie the callback is attached even before the $.ajax call returns and your done and then handlers can be attached. 并且prefilter在$.ajax内部执行,即,甚至在$.ajax调用返回之前,也可以附加回调, then可以附加您的done和handler。

All .then does if you don't return a deferred object is add another done fail and/or progress handler to the deferred object. 如果您不返回延迟的对象,则所有.then要做的就是向该延迟的对象添加另一个完成的失败和/或进度处理程序。 with that in mind, it makes complete sense for the .then added in the pre-filter to execute before the one added after $.ajax() because the code in the pre-filter callback happened first. 考虑到这一点,在预过滤器中添加$.ajax()$.ajax()之后添加的$.ajax()之前执行是完全有意义的.then因为pre-filter回调中的代码首先发生。 The callbacks get triggered first in first out. 回调先入先出。

What I don't understand is why the prefilter step executes first. 我不明白的是为什么要先执行预过滤器步骤。 I would have expected it to have been executed last, or not at all. 我希望它最后执行一次,或者根本不执行。

You've attached another "thing to do" to the jqXHR that is associated with the ajax request. 您已经将另一个“要做的事情”附加到了与ajax请求关联的jqXHR上。 Since it's a pre -filter, that gets attached before the standard done/fail that the ajax request uses. 由于它是一个过滤器,因此会在ajax请求使用的标准完成/失败之前被附加。 Handlers run in the order they were attached and the prefilter one is therefore first. 处理程序按其连接的顺序运行,因此预过滤器是第一个。

Note that since the prefilter only attached a single function in the .then() method, nothing will run if the request fails for some reason. 请注意,由于预过滤器仅在.then()方法中附加了单个功能,因此.then()如果由于某种原因请求失败,将不会运行任何内容。 Sounds like you'd want to have the second (failure handler) arg as well. 听起来您也想拥有第二个(故障处理程序)arg。

As for the completion order of the two different ajax requests, that is not predictable. 至于两个不同的ajax请求的完成顺序,这是不可预测的。 It will just depend on which one returns first. 这将取决于哪个先返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么jQuery的行为与javascript不同? - Why does jQuery behave differently than javascript? 为什么jQuery.val()与其他jQuery的行为有所不同 - Why does jQuery.val() behave differently to the rest of jQuery 为什么jQuery on / off方法的行为与外部脚本不同 - Why does jQuery on/off method behave differently from external script 在ReactJS中,为什么`setState`在同步调用时表现不同? - In ReactJS, why does `setState` behave differently when called synchronously? 为什么/ * * /注释的行为不同? Javascript错误? - Why does /* */ comment behave differently ? Javascript bug? 为什么deferred.resolve的行为与q手册中指定的不同? - Why does deferred.resolve not behave as specified in the q manual? 当我在同一目录或父目录中时,为什么“require”的行为会有所不同? - Why does “require” behave differently when I am in the same directory or a parent directory? 为什么在执行递归回调时 .foreach 的行为与 for...of 不同? - Why does .foreach behave differently than for...of when executing a recursive callback? 为什么 oninput 事件在 Angular 中的行为与在 JavaScript 中的行为不同? - Why does the oninput event behave differently in Angular than it does in JavaScript? 延迟使用jQuery链接和排队Ajax请求 - Chaining and queuing ajax requests using jQuery deferred
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM