如何在自动调用的功能(例如.ajax()的beforeSend())上正确利用jQuery Deferred/promise? [英] How to properly utilize jQuery Deferred/promise on auto-invoked function such as .ajax()'s beforeSend()?
问题描述
我正在扩展jQuery的ajaxPrefilter
接口,以向AJAX调用添加其他功能;即使用beforeSend()
方法中的setRequestHeader()
将标头数据附加到XHR请求上.事实是,ajaxPrefilter
和ajax调用本身都可以包含beforeSend
选项,并且它们之一或两者都可以包含异步功能.
I'm working on extending jQuery's ajaxPrefilter
interface to add additional functionality to AJAX calls; namely tacking header data onto the XHR request using setRequestHeader()
within the beforeSend()
method. The thing is, both the ajaxPrefilter
and ajax call itself could contain beforeSend
options, and one or both of them could contain async functionality.
假设我的ajaxPrefilter
看起来像这样:
Assume my ajaxPrefilter
looks as such:
(function($) {
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
var auth = $.cookie("fake_site"),
normalizedRequest = $.Deferred();
if (originalOptions.authorizeUser) {
options.beforeSend = function() {
jqXHR.setRequestHeader("Authorization", "Session " + auth);
}
// resolving the jqXHR Deferred, statusCode handling, etc.
}
});
})(jQuery);
现在,选项和原始选项都可以包含beforeSend()
方法,我希望 options.beforeSend 始终先执行.这似乎是延迟/承诺用法的主要候选者,但是由于beforeSend
是自动调用的,所以我不能这样做:
Now, both options and originalOptions could contain beforeSend()
methods, and I want options.beforeSend to ALWAYS execute first. This would seem like a prime candidate for Deferred/promise usage, but due to the fact that beforeSend
is automatically invoked, I can't do this:
options.beforeSend = function(jqXHR) {
// setting the request header; creating, resolving, and returning the Deferred
}
$.when(options.beforeSend(jqXHR)).then(function() {
originalOptions.beforeSend();
});
如预期的那样,这会导致options.beforeSend
触发两次;都归功于其定义声明和$.when
调用.
As expected, this causes options.beforeSend
to fire twice; both due to its definition statement and the $.when
call.
如何使用延期/承诺来管理自动调用的方法,例如beforeSend
?
How would Deferreds/promises be used to manage auto-invoked methods such as beforeSend
?
推荐答案
关于控制beforeSend
回调后发生的情况,只有两个选项:
With regard controlling to what happens after a beforeSend
callback, there are only two options :
- 返回false以外的任何内容以允许请求继续进行,或者
- 返回
false
取消请求.
- return anything other than false to allow the request to proceed, or
- return
false
to cancel the request.
您确实可以在回调中发出ajax请求,但是返回的任何内容都会导致原始(外部)ajax请求被立即发出或取消.由于回调将完成并无条件返回,因此无法通过延迟或其他方式使外部ajax依赖于内部.
You could indeed issue an ajax request within the callback but whatever is returned will cause the original (outer) ajax request to be issued issued immediately, or canceled. As the callback will complete and return unconditionally, it's not possible to make the outer ajax dependent on the inner by way of a deferred or otherwise.
要获得所需的效果,您可以在回调中以级联方式发出两个ajax请求(第二个依赖于第一个),然后返回false
取消原始请求.
For the effect you want, you could, within the callback, issue two ajax requests in cascade (the second being dependent on the first) and return false
to cancel the original request.
有一天,您可能想采用这种模式可能有一些晦涩的原因,但是,如果无条件地丢弃原始请求(通过返回false),那么它仅是一种复杂的方法,可以在其中实现两个ajax请求级联,不涉及beforeSend
,即:
One day, there might be some obscure reason why you might want to adopt this pattern but, if the original request is discarded unconditionally (by returning false), it would be nothing more than a convoluted way of achieving two ajax requests in cascade, not involving beforeSend
, ie.:
$.ajax({
//options
}).done(function() {
$.ajax({
//options
}).done(function(){
//do stuff here
});
});
或.pipe()
等价物.
总而言之,似乎不可能使jQuery ajax请求依赖于其beforeSend
回调中编码的另一个异步操作,但是可以通过不涉及beforeSend
的标准方式来实现所需的效果.
In summary, it appears to be impossible make a jQuery ajax request dependent on another asynchronous action coded in its beforeSend
callback, however the desired effect can be achieved by standard means not involving beforeSend
.
这篇关于如何在自动调用的功能(例如.ajax()的beforeSend())上正确利用jQuery Deferred/promise?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!