jQuery的deferred对象详解(二)

  Deferred对象是由$.Deferred构造的,$.Deferred被实现为简单的工厂模式。

  $.Deferred的实现

  1. 创建三个$.Callbacks对象,分别表示成功done,失败fail,处理中process三种状态
  2. 对应了三种处理结果,resolve、reject、notify
  3. 创建了一个promise对象,具有state、always、then、primise方法
  4. 通过扩展primise对象生成最终的Deferred对象,是阻止其他代码来改变这个deferred对象的状态,deferred.promise() 改变不了 deferred 对象的状态,作用也不是保证目前的状态不变

  上面提到Deferred里面的3个$.Callback()的实例,Deferred自身则围绕这三个对象进行更高层次的抽象。以下是Deferred对象的核心方法

  1.done/fail/progress是callbacks.add,将回调函数增加到回调管理器

  2.resolve/reject/notify是callback.fire,执行回调函数(或队列)

  $.Deferred成员的方法

  1.$.Deferred()

  生成一个异步队列实例对象deferred

  接受一个function参数,function里边可以使用this来调用当前的异步队列实例

  2.deferred.done(fn)

  成功时触发的回调fn

  3.deferred.fail(fn)

  失败时触发的回调

  4.deferred.progress(fn)

  处理中触发的回调

  5.deferred.resolve/resolveWith([context],args)

  这里等同$.Callbacks().(fire/fireWith)

  在任务处理成功之后使用此方法触发成功事件,之前加入done队列的回调会被触发

  6.deferred.reject/rejectWith([context],args)

  这里等同$.Callbacks().(fire/fireWith)

  在任务处理成功之后使用此方法触发成功事件,之前加入fail队列的回调会被触发

  7.deferred.notify/notifyWith([context],args)

  这里等同$.Callbacks().(fire/fireWith)

  在任务处理中可以使用此方法触发正在处理的事件

  8.deferred.promise()

  deferred.promise() 只是阻止其他代码来改变这个 deferred 对象的状态,通过 deferred.promise() 方法返回的 deferred 对象,是没有 resolve ,reject, progress , resolveWith, rejectWith , progressWith 这些可以改变状态的方法

  9.deferred.then([fnDone,fnFail,fnProgress])

  可以直接传入三个回调函数,分别对应done|fail|progress三个状态的回调,例$.when($.ajax("/main.php")).then(successFunc,failureFunc,proFunc),第一个参数是done()方法的回调函数,第二个参数是fail方法的回调函数,第三个是progress的回调函数,也可以只传一个参数,则是done()方法的回调函数

  10.deferred.always(fn)

  不管最后是resolve还是reject,都会触发fn

  11.$.when(mission1,[mission2,mission3,...])

  这个事挂载在jQuery上的方法, 为多个操作指定回调函数,例$.when($.ajax("test1.html",$.ajax("test2.html"))).done(fn).fail(fn)

  $.Deferred源码结构

  

   // Deferred 委托人对象,对委托人管理
    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")]
            ],
            promise = {
                state: function () {
                    return state;
                },

                always: function () {
                    deferred.done(arguments).fail(arguments);
                    return this;
                },

                then: function ( /* fnDone, fnFail, fnProgress */) {
                    // 声明一个变量,并把参数引用赋值给funs
                    var fns = arguments;
                    // newDefer 创建一个新的委托人
                    return jQuery.Deferred(function (newDefer) {
                        jQuery.each(tuples, function (i, tuple) {

                        });
                        // 清空变量,内存回收
                        fns = null;
                    }).promise();//返回一个受到限制的委托人
                },

                promise: function (obj) {
                    return obj != null ? jQuery.extend(obj, promise) : promise;
                }
            },
            // 声明变量 创建一个委托人
            deferred = {};
 
            // 添加一个方法名pipe与then相同,一般使用pipe进行filter操作
            promise.pipe = promise.then;
 
            jQuery.each(tuples, function (i, tuple) {
                //声明一个局部变量,将观察器对象引用给list  
                var list = tuple[2],
                    stateString = tuple[3]; //委托人的最终状态
 
                promise[tuple[1]] = list.add;

                // 将委托人的通知和观察者对象的执行回调函数(观察者函数) 联系起来
                deferred[tuple[0]] = function () {
                    deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments);
                    return this;
                };
                deferred[tuple[0] + "With"] = list.fireWith;
            });
 
            // 为委托人添加一个被限制的委托人对象 (将promise对象extend到deferred中)
            promise.promise(deferred);
 
            // 检测func是否存在,存在将生成的委托人对象作为这个函数的默认参数,以及将this指向这个委托人
            if (func) {
                func.call(deferred, deferred);
            }
 
            // 返回委托人对象
            return deferred;
        },
 
        when: function (subordinate /* , ..., subordinateN */) {
            var i = 0,
                resolveValues = core_slice.call(arguments),
                progressValues, progressContexts, resolveContexts;

            if (!remaining) {
                deferred.resolveWith(resolveContexts, resolveValues);
            }
 
            return deferred.promise();
        }
    });

 

  

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。