I've been trying to get my head around the jQuery Deferred object. My intention is to inspect each ajax response (success/fail). I want to do this without interfering with other code that declares a typical $.ajax().done().fail() request.
我一直在尝试了解jQuery Deferred对象。我的目的是检查每个ajax响应(成功/失败)。我希望在不干扰声明$.ajax().done().fail()请求的其他代码的情况下实现这一点。
I've user the $.ajaxPrefilter() to get each ajax request before it is executed. 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
我使用$. ajaxprefilter()在执行ajax请求之前获取每个请求。使用jqXHR对象上的then()方法,我添加了一个函数,该函数将在放置在原始$.ajax()调用上的.done()方法之前被调用
The code below will print out the following:
下面的代码将打印出以下内容:
def done
def then
2nd ajax prefilter then
2nd ajax done
2nd ajax then
ajax done
ajax then然后是第二个ajax预过滤器,然后是第二个ajax,然后是ajax,然后是ajax。
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.
我不明白的是为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本不会被执行。
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().
下面的代码演示了如何在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
done is called function
2nd ajax prefilter then
2nd ajax done
2nd ajax then预滤器函数在美元。ajax调用done被称为函数二ajax预过滤器第二ajax做第二ajax然后第二ajax做第二ajax
Which answers my question about how the .then() method is attached to the deferred jqXHR object before the .done() method.
这就回答了我的问题,即在.done()方法之前,then()方法是如何附加到延迟的jqXHR对象上的。
3 个解决方案
#1
3
In your case, there is no difference between adding callbacks with .done()
or with .then()
. Using only .done()
would be enough.
在您的示例中,使用.done()或with .then()添加回调没有区别。只用.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.
我不明白的是为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本不会被执行。
Callbacks are executed in the order they are added to the deferred object. And the prefilter is executed inside of $.ajax
, i.e. the callback is attached even before the $.ajax
call returns and your done
and then
handlers can be attached.
回调按添加到deferred对象的顺序执行。预过滤器在$中执行。ajax,即回调在$ $之前就连上了。ajax调用返回,完成,然后可以附加处理程序。
#2
1
All .then
does if you don't return a deferred object is add another done fail and/or progress handler to the deferred object. 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. The callbacks get triggered first in first out.
然后,如果您不返回一个延迟对象,则会向延迟对象添加另一个已完成的失败和/或进程处理程序。考虑到这一点,在.ajax() $.ajax()之后添加的代码之前,添加在预筛选器中的then完全有意义,因为预筛选回调中的代码首先发生。回调首先被触发。
#3
1
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.
我不明白的是为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本不会被执行。
You've attached another "thing to do" to the jqXHR that is associated with the ajax request. Since it's a pre-filter, that gets attached before the standard done/fail that the ajax request uses. Handlers run in the order they were attached and the prefilter one is therefore first.
您已经将另一个“要做的事情”附加到与ajax请求关联的jqXHR。因为它是一个预筛选器,在ajax请求使用的标准done/fail之前附加它。处理程序按照附加的顺序运行,因此预筛选器是第一个。
Note that since the prefilter only attached a single function in the .then()
method, nothing will run if the request fails for some reason. Sounds like you'd want to have the second (failure handler) arg as well.
注意,由于prefilter只在then()方法中附加了一个函数,因此如果由于某种原因请求失败,则不会运行任何函数。听起来您也想要第二个(故障处理程序)arg。
As for the completion order of the two different ajax requests, that is not predictable. It will just depend on which one returns first.
至于两个不同的ajax请求的完成顺序,这是不可预测的。它只取决于哪一个先返回。
#1
3
In your case, there is no difference between adding callbacks with .done()
or with .then()
. Using only .done()
would be enough.
在您的示例中,使用.done()或with .then()添加回调没有区别。只用.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.
我不明白的是为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本不会被执行。
Callbacks are executed in the order they are added to the deferred object. And the prefilter is executed inside of $.ajax
, i.e. the callback is attached even before the $.ajax
call returns and your done
and then
handlers can be attached.
回调按添加到deferred对象的顺序执行。预过滤器在$中执行。ajax,即回调在$ $之前就连上了。ajax调用返回,完成,然后可以附加处理程序。
#2
1
All .then
does if you don't return a deferred object is add another done fail and/or progress handler to the deferred object. 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. The callbacks get triggered first in first out.
然后,如果您不返回一个延迟对象,则会向延迟对象添加另一个已完成的失败和/或进程处理程序。考虑到这一点,在.ajax() $.ajax()之后添加的代码之前,添加在预筛选器中的then完全有意义,因为预筛选回调中的代码首先发生。回调首先被触发。
#3
1
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.
我不明白的是为什么prefilter步骤首先执行。我原以为它最后会被执行,或者根本不会被执行。
You've attached another "thing to do" to the jqXHR that is associated with the ajax request. Since it's a pre-filter, that gets attached before the standard done/fail that the ajax request uses. Handlers run in the order they were attached and the prefilter one is therefore first.
您已经将另一个“要做的事情”附加到与ajax请求关联的jqXHR。因为它是一个预筛选器,在ajax请求使用的标准done/fail之前附加它。处理程序按照附加的顺序运行,因此预筛选器是第一个。
Note that since the prefilter only attached a single function in the .then()
method, nothing will run if the request fails for some reason. Sounds like you'd want to have the second (failure handler) arg as well.
注意,由于prefilter只在then()方法中附加了一个函数,因此如果由于某种原因请求失败,则不会运行任何函数。听起来您也想要第二个(故障处理程序)arg。
As for the completion order of the two different ajax requests, that is not predictable. It will just depend on which one returns first.
至于两个不同的ajax请求的完成顺序,这是不可预测的。它只取决于哪一个先返回。