Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在自动调用的函数(如.ajax()')上正确使用jQuery Deferred/promise;s beforeSend()?_Ajax_Jquery_Jquery Deferred - Fatal编程技术网

如何在自动调用的函数(如.ajax()')上正确使用jQuery Deferred/promise;s beforeSend()?

如何在自动调用的函数(如.ajax()')上正确使用jQuery Deferred/promise;s beforeSend()?,ajax,jquery,jquery-deferred,Ajax,Jquery,Jquery Deferred,我正在扩展jQuery的ajaxPrefilter接口,为AJAX调用添加额外的功能;即使用beforeSend()方法中的setRequestHeader()将标头数据固定到XHR请求上。问题是,ajaxPrefilter和ajax调用本身都可以包含beforeSend选项,其中一个或两个都可以包含异步功能 假设我的ajaxPrefilter看起来是这样的: (function($) { $.ajaxPrefilter(function(options, originalOptions

我正在扩展jQuery的
ajaxPrefilter
接口,为AJAX调用添加额外的功能;即使用
beforeSend()
方法中的
setRequestHeader()
将标头数据固定到XHR请求上。问题是,
ajaxPrefilter
和ajax调用本身都可以包含
beforeSend
选项,其中一个或两个都可以包含异步功能

假设我的
ajaxPrefilter
看起来是这样的:

(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()
方法,我希望选项。beforeSend始终首先执行。这似乎是延迟/承诺用法的主要候选项,但由于自动调用了
beforeSend
,因此我不能这样做:

options.beforeSend = function(jqXHR) {
    // setting the request header; creating, resolving, and returning the Deferred
}

$.when(options.beforeSend(jqXHR)).then(function() {
    originalOptions.beforeSend();
});
正如预期的那样,这会导致
选项。beforeSend
触发两次;由于其定义语句和调用时的
$


如何使用延迟/承诺来管理自动调用的方法,例如
beforeSend

关于控制
beforeSend
回调后发生的情况,只有两个选项:

  • 返回除false以外的任何内容以允许请求继续,或
  • 返回
    false
    以取消请求
您确实可以在回调中发出ajax请求,但是返回的任何内容都会导致立即发出或取消原始(外部)ajax请求。由于回调将完成并无条件返回,因此不可能通过延迟或其他方式使外部ajax依赖于内部ajax

为了达到您想要的效果,您可以在回调中级联发出两个ajax请求(第二个请求依赖于第一个请求),并返回
false
以取消原始请求

有一天,可能会有一些模糊的原因让您想采用这种模式,但是,如果原始请求被无条件地丢弃(返回false),那么它只不过是一种以级联方式实现两个ajax请求的复杂方式,而不涉及在发送之前的
,即:

$.ajax({
    //options
}).done(function() {
    $.ajax({
        //options
    }).done(function(){
        //do stuff here
    });
});
或类似的
.pipe()


总之,使jQuery ajax请求依赖于在其
beforeSend
回调中编码的另一个异步操作似乎是不可能的,但是可以通过不涉及
beforeSend
的标准方法来实现所需的效果。下面的方法有点难看,但可以全局处理重新启动原始请求,而不是嵌套每个请求。例如,如果您需要一个令牌,但该令牌已过期,则此示例依赖于全局api.getToken()函数返回的承诺

$.ajaxSetup({
  beforeSend: function(xhr,settings) {
    var newTokenNeeded = false;
    var originalSettings=settings;

        var promise = api.getToken().then(function(data){

            if(newTokenNeeded && typeof originalSettings.nested ==='undefined'){
                originalSettings.nested=true;//this flag is used to prevent infinite loops
                $.ajax(originalSettings);//here we re request the original, that we cancelled previously
            }else{
                xhr.setRequestHeader('Authorization', 'Bearer ' +data.t );
            }
        });
        if(promise.state()==='pending'){
            newTokenNeeded=true;
            return false; //returning false cancels the original request
        }
  }

});