• jQuery deferred学习笔记


    简介


      在jQuery1.5.0版本引入,为了实现Deferred对象,jQuery改写了ajax。是由jQuery.Deferred()方法创建的链式对象。

      $.Deferred在jQuery代码自身四处被使用(promiseDOM ready、Ajax、Animation)

      

      特性:使用Deferred对象可以添加多个回调函数; 延迟特性,处理耗时操作问题

    •  register multiple callbacks into callback queues
    •  invoke callback queues
    •  relay the success or failure state of any synchronous or asynchronous function

    主要源码


    jQuery1.9.1源码如下:

    jQuery.extend({
    
        Deferred: function( func ) {
            var tuples = [
                    // action, add listener, listener list, final state
                    [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
                    [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
                    [ "notify", "progress", jQuery.Callbacks("memory") ]
                ],
                state = "pending",
                promise = {
                    state: function() {
                       .....
                    },
                    always: function() {
                       ....
                    },
                    then: function( /* fnDone, fnFail, fnProgress */ ) {
               ....
                    },
                    // Get a promise for this deferred
                    // If obj is provided, the promise aspect is added to the object
                    promise: function( obj ) {
                      .....
                    }
                },
                deferred = {};
    
            // Keep pipe for back-compat
            promise.pipe = promise.then;
    
            // Add list-specific methods
            jQuery.each( tuples, function( i, tuple ) {
                ...
                deferred[ tuple[0] + "With" ] = list.fireWith;
            });
    
            // Make the deferred a promise
            promise.promise( deferred );
    
            // Call given func if any
            if ( func ) {
                func.call( deferred, deferred );
            }
    
            // All done!
            return deferred;
        },
    
        // Deferred helper
        when: function( subordinate /* , ..., subordinateN */ ) {
        ....
        return deferred.promise();
      }
        
    });

    Callbacks 是jQuery的回调对象,用于添加回调、删除回调、执行回调等

    jQuery.Callbacks = function( options ) {// Actual Callbacks object
            self = {
                // Add a callback or a collection of callbacks to the list
                add: function() {
                    ...
                },
                // Remove a callback from the list
                remove: function() {
                   ....
                },
           ....
    // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; };

     

    methods


       jQuery下两个方法:

      

    $.Deffered() ——创建Deffered对象,var deferred = $.Deffered();
    
    $.when()——为多个操作指定回调函数

      

      Deffered对象包含如下方法:

    deferred.always()——执行回调函数,不管deffered 对象是 状态resolved或者是rejected
               (即不管成功或者失败,对应ajax中complete)(关于执行状态看下一章节)
    
    deferred.done()——当Deferred对象状态为resolved时执行回调函数
    
    deferred.fail()——当Deferred对象状态为rejected时执行回调函数
    
    deferred.then()——执行回调函数,deferred 对象是 状态resolved或者是rejected 或者是 in progress
    deferred.isRejected()——判断状态是否为rejected
    
    deferred.isResolved()——判断状态是否为resolved
    
    deffered.state()——判断当前状态
    deferred.promise()——返回Deferred的promise对象
    
    deferred.reject()——reject a deferred对象,即将状态转为rejected( with the given args.)
    
    deferred.rejectWith()——与上面reject的区别:with the given context and args. 下面类似
    
    deferred.resolve()——即将状态转为resolve  
                  
    deferred.resolveWith()—— 

    deferred.notify()——call the progressCallbacks  
    
    deferred.notifyWith()——  
     
     
    
    deferred.pipe()——过滤参数
     

    一般done/resolve fail/reject progress/notify 对应使用



    执行状态


      Deffered对象三种执行状态: resolved(已完成)、未完成、rejected(失败)

      1. 如果执行状态是resovled,Deffered对象会立刻调用done()方法指定的回调函数

      2. 如果执行状态是rejected,Deffered对象会立刻调用fail()方法指定的回调函数

      3.  如果执行状态是未完成,Deffered对象会继续等待或者是调用progress()方法指定的回调函数

    ajax及简单链式操作


    eg:

    ajax方式:

    $.ajax("test.jsp").success(function(result){alert("success! data is :"+result);})   
                      .error(function(){alert("Error")})
               .complete(function(){alert("complete!")});
    
    或者:
    
    $.ajax({
            url:"test.jsp",
            success:function(result){alert("success! data is :"+result);},
         error: function(){alert("Error!");},
           complete:function(){alert("complete!")},
    });

    使用Deferred:

    由于$.ajax 方法和$.get方法返回的是jqXHR对象(源自Deferred对象)因而上面的操作可以以下面的方式实现。

        $.ajax("test.jsp").done(function(result){alert("success! data is :"+result);})
                          .fail(function(){alert("Error")})
                 .always(function(){alert("finished");});

     注意:$.ajax()中jqXHR.success(), jqXHR.error(), jqXHR.complete(), 在jquery 1.8中已经弃用,应该使用done(),fail()和always()

    done/resolve   fail/reject   progress/notify


    done/resolve

    var dfd = $.Deferred();
    
    dfd.done(function(){
        console.log("###############")
    });
    
    $("button").on("click",function(){
        dfd.resolve();
    }); 

    点击按钮,输出  ###############

    fail/reject

    var dfd = $.Deferred();
    
    dfd.fail(function(){
        console.log("###############")
    });
    
    $("button").on("click",function(){
        dfd.reject();
    }); 

    点击按钮,输出  ###############

    progress/notify

    eg1:

    var dfd = $.Deferred();
    
    dfd.progress(function(){
        console.log("###############")
    });
    
    $("button").on("click",function(){
        dfd.notify();
    }); 

    点击按钮,输出  ###############

    eg2:使用notify间隔的执行回调函数

    var dfd = $.Deferred();
    
    dfd.progress(function(){
        console.log("###############");
    });
    
    $("button").on("click",function(){
        setInterval(function(){
            dfd.notify();
        },1000);
        
    });  

    点击按钮,每1s输出一次##################

     

    执行多个回调函数


    eg1:

        $.ajax("test.jsp").done(function(){console.log("the first callback");})
                          .done(function(){console.log("the second callback");})
                          .done(function(){console.log("the third callback");})
                          .fail(function(){console.log("Error")});
    
    或者:
    
    $.ajax("test.jsp").success(function(){console.log("the first callback");})
               .success(function(){console.log("the second callback");})
               .success(function(){console.log("the third callback");})
               .error(function(){console.log("Error")});

    输出:

    the first callback
    the second callback
    the third callback

    eg2:

    deferred对象的done方法定义如下:deferred.done( doneCallbacks [, doneCallbacks ] ) 可以传入 array of functions

    success也可达到相同效果,但是已弃用不建议使用

         $.ajax("test.jsp").done([f1,f2,f3],[f2,f3])
                          .done(function(){console.log("the fourth callback");})
                          .fail(function(){alert("Error")});
        function f1(){
            console.log("the first callback");
        }
        function f2(){
            console.log("the second callback");
        }
        function f3(){
            console.log("the third callback");
        }

    输出结果如下:

    the first callback
    the second callback
    the third callback
    the second callback
    the third callback
    the fourth callback

    eg3: 使用jQuery.Deferred()创建Deferred对象

    简单使用done方法和resolve方法

    function f1(){
        console.log("the first callback");
    }
    function f2(){
        console.log("the second callback");
    }
    function f3(){
        console.log("the third callback");
    } 
    
    var dfd = $.Deferred();
    dfd.done([f1,f2,f3],[f2,f3])
       .done(function(){console.log("finished");});
    $("button").on("click",function(){
        dfd.resolve();
    });

    点击button,输出:

    the first callback
    the second callback
    the third callback
    the second callback
    the third callback
    finished

    eg4. 给resolve添加args

    function f1(arg){
        console.log(arg+"the first callback");
    }
    function f2(arg){
        console.log(arg+"the second callback");
    }
    function f3(arg){
        console.log(arg+"the third callback");
    } 
    
    var dfd = $.Deferred();
    dfd.done([f1,f2,f3],[f2,f3])
       .done(function(){console.log("finished");})
       .always(function(arg){console.log(arg+"end");});
       
    $("button").on("click",function(){
        dfd.resolve("###############");
    });

    输出如下:

    ###############the first callback
    ###############the second callback
    ###############the third callback
    ###############the second callback
    ###############the third callback
    finished
    ###############end

     then和pipe


     pipe

    使用pipe可以过滤参数,但是jQuery 1.8后已经启用pipe方法,建议使用then

    pipe方法定义为:deferred.pipe( [doneFilter ] [, failFilter ] [, progressFilter ] )    returns a new promise

    eg1:一次性定义done fail 和progress

    function f1() {
        console.log('done');
    }
    function f2() {
        console.log('fail');
    }
    function f3() {
        console.log('progress');
    }
    var deferred = $.Deferred();
    deferred.pipe(f1, f2, f3);
    $("button").on("click",function(){
        deferred.reject();
    });

    点击按钮,输出 fail, 可以根据需要修改deferred.reject 为resolve或者是notify

    eg2: 

    var dfd = $.Deferred();
    dfd.pipe(function(arg){return "(*^__^*)"+arg;});
    
    dfd.done(function(arg){
        console.log(arg)
    });
    
    $("button").on("click",function(){
        dfd.resolve("###############");
    });

    点击按钮输出:

    (*^__^*)###############

    eg3:

    var dfd = $.Deferred();
        argFilter = dfd.pipe(null, function(arg){return "(*^__^*)"+arg;});
    
    argFilter.fail(function(arg){
        console.log(arg)
    });
    
    $("button").on("click",function(){
        dfd.reject("###############");
    });

    输出结果同上

     then 

     deferred.then( [doneFilter ] [, failFilter ] [, progressFilter ] )  

    function f1() {
        console.log('done');
    }
    function f2() {
        console.log('fail');
    }
    function f3() {
        console.log('progress');
    }
    var deferred = $.Deferred();
    deferred.then(f1, f2, f3);
    $("button").on("click",function(){
        deferred.reject();
    });

    效果同pipe

     when为多个操作指定回调函数


    jQuery.when(deferreds);

    如果传入单个deferred, 返回promise对象,后面可以链式添加then等方法

    如果传入多个deferred,返回a new master deferred对象,该对象集合所有deferred对象的状态,如果所有deferred对象是resollve则结果是resolve,如果有一个是reject则结果是reject

    eg1:

    $.when($.ajax("test.jsp")).done(function(){console.log("done");});

    结果:

    GET http://localhost:8080/javascript/jQuery/test.jsp  200 OK 83ms    
    
    done

    eg2:

    function f1() {
        console.log('done');
    }
    function f2() {
        console.log('fail');
    }
    function f3() {
        console.log('progress');
    }
    $.when($.ajax("test.jsp")).then(f1,f2,f3);

    结果同上

    eg3:

    $.when($.ajax("test.jsp"),$.ajax("demo.jsp")).done(function(){console.log("done");});

    结果:

    GET http://localhost:8080/javascript/jQuery/test.jsp  200 OK 83ms    
    
    GET http://localhost:8080/javascript/jQuery/demo.jsp   200 OK 460ms    
    
    done

    eg4:

     <style>
    div {
        height: 50px;
        width: 50px;
        float: left;
        margin-right: 10px;
        display: none;
        background-color: #090;
      }
      </style>
    <button>button</button>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    var effect = function() {
      return $( "div" ).fadeIn( 800 ).delay( 1200 ).fadeOut();
    };
     
    $( "button" ).on( "click", function() {
      $.when( effect() ).done(function() {
        console.log("finished");
      });
    });

    effect()方法执行完后输出 finished;

     .promise()


    .promise([type][,target])  return a promise object   当所有与其相关的action结束后变为resolve状态

    (The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended.)

    eg1:

    var button = $( "<button>" );     
    button.promise().done(function( arg ) {
         console.log( this === button && arg === button );  //true
    });

    eg2:

     <style>
    div {
        height: 50px;
        width: 50px;
        float: left;
        margin-right: 10px;
        display: none;
        background-color: #090;
      }
      </style>
    <button>button</button>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    $( "button" ).on( "click", function() {
     
      $( "div" ).each(function( i ) {
        $( this ).fadeIn().fadeOut( 1000 * ( i + 1 ) );
      });
     
      $( "div" ).promise().done(function() {
        console.log("finished");
      });
    });

    animation结束后输出finished,效果等价于when 中的eg4

    相关: http://api.jquery.com/category/deferred-object/

         http://www.cnblogs.com/littledu/articles/2811728.html

       http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

  • 相关阅读:
    css中vertical-align(垂直对齐)的使用
    CSS教程:div垂直居中的N种方法[转]
    前后端分离开发部署模式
    <a>标签的href和onclick属性
    css 字体样式
    谷歌开发者工具界面介绍
    cps和dsp渠道手法的研究
    网络资源汇总
    DataWorks(数据工场)
    vue入门学习笔记
  • 原文地址:https://www.cnblogs.com/wishyouhappy/p/3747311.html
Copyright © 2020-2023  润新知