<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

        jquery1.83之前所有與異步列隊相關(guān)的模塊詳細(xì)介紹_jquery

        來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 21:05:28
        文檔

        jquery1.83之前所有與異步列隊相關(guān)的模塊詳細(xì)介紹_jquery

        jquery1.83之前所有與異步列隊相關(guān)的模塊詳細(xì)介紹_jquery:jQuery在1.5引入了Deferred對象(異步列隊),當(dāng)時它還沒有劃分為一個模塊,放到核心模塊中。直到1.52才分割出來。它擁有三個方法:_Deferred, Deferred與when。 出于變量在不同作用域的共用,jQuery實現(xiàn)異步列隊時不使用面向?qū)ο蠓绞剑裚Deferre
        推薦度:
        導(dǎo)讀jquery1.83之前所有與異步列隊相關(guān)的模塊詳細(xì)介紹_jquery:jQuery在1.5引入了Deferred對象(異步列隊),當(dāng)時它還沒有劃分為一個模塊,放到核心模塊中。直到1.52才分割出來。它擁有三個方法:_Deferred, Deferred與when。 出于變量在不同作用域的共用,jQuery實現(xiàn)異步列隊時不使用面向?qū)ο蠓绞剑裚Deferre

        jQuery在1.5引入了Deferred對象(異步列隊),當(dāng)時它還沒有劃分為一個模塊,放到核心模塊中。直到1.52才分割出來。它擁有三個方法:_Deferred, Deferred與when。

        出于變量在不同作用域的共用,jQuery實現(xiàn)異步列隊時不使用面向?qū)ο蠓绞剑裚Deferred當(dāng)作一個工廠方法,返回一個不透明的函數(shù)列隊。之所以說不透明,是因為它的狀態(tài)與元素都以閉包手段保護(hù)起來,只能通過列隊對象提供的方法進(jìn)行操作。這幾個方法分別是done(添加函數(shù)),resolveWith(指定作用域地執(zhí)行所有函數(shù)),resolve(執(zhí)行所有函數(shù)),isResolved(判定是否已經(jīng)調(diào)用過resolveWith或resolve方法),cancel(中斷執(zhí)行操作)。但_Deferred自始至終都作為一個內(nèi)部方法,從沒有在文檔中公開過。

        Deferred在1.5是兩個_Deferred的合體,但1+1不等于2,它還是做了增強(qiáng)。偷偷爆料,Deferred本來是python世界大名鼎鼎的Twisted框架的東西,由早期七大JS類庫中的MochiKit取經(jīng)回來,最后被dojo繼承衣缽。jQuery之所以這樣構(gòu)造Deferred,分明不愿背抄襲的惡名,于是方法改得一塌糊涂,是jQuery命名最差的API,完全不知所云。它還加入當(dāng)時正在熱烈討論的promise機(jī)制。下面是一個比較列表:

        dojo jQuery 注解
        addBoth then 同時添加正?;卣{(diào)與錯誤回調(diào)
        addCallback done 添加正?;卣{(diào)
        addErrback fail 添加錯誤回調(diào)
        callback done 執(zhí)行所有正常回調(diào)
        errback reject 執(zhí)行所有錯誤回調(diào)
        doneWith 在指定作用域下執(zhí)行所有正?;卣{(diào),但dojo已經(jīng)在addCallback上指定好了
        rejectWith 在指定作用域下執(zhí)行所有錯誤回調(diào),但dojo已經(jīng)在addErrback上指定好了
        promise 返回一個外界不能改變其狀態(tài)的Deferred對象(外稱為Promise對象)

        jQuery的when方法用于實現(xiàn)回調(diào)的回調(diào),或者說,幾個異列列隊都執(zhí)行后才執(zhí)行另外的一些回調(diào)。這些后來的回調(diào)也是用done, when, fail添加的,但when返回的這個對象已經(jīng)添加讓用戶控制它執(zhí)行的能力了。因為這時它是種叫Promise的東西,只負(fù)責(zé)添加回調(diào)與讓用戶窺探其狀態(tài)。一旦前一段回調(diào)都觸發(fā)了,它就自然進(jìn)入正常回調(diào)列隊(deferred ,見Deferred方法的定義)或錯誤回調(diào)列隊(failDeferred )中去。不過我這樣講,對于沒有異步編程經(jīng)驗的人來說,肯定聽得云里霧里??磳嵗昧?。
        代碼如下:
        $.when({aa:1}, {aa:2}).done(function(a,b){
        console.log(a.aa)
        console.log(b.aa)
        });

        直接輸出1,2。如果是傳入兩個函數(shù),也是返回兩個函數(shù)。因此對于普通的數(shù)據(jù)類型,前面的when有多少個參數(shù),后面的done, fail方法的回調(diào)就有多少個參數(shù)。
        代碼如下:
        function fn(){
        return 4;
        }
        function log(s){
        window.console && console.log(s)
        }
        $.when( { num:1 }, 2, '3', fn() ).done(function(o1, o2, o3, o4){
        log(o1.num);
        log(o2);
        log(o3);
        log(o4);
        });

        如果我們想得到各個異步的結(jié)果,我們需要用resolve, resolveWith, reject, rejectWith進(jìn)行傳遞它們。
        代碼如下:
        var log = function(msg){
        window.console && console.log(msg)
        }
        function asyncThing1(){
        var dfd = $.Deferred();
        setTimeout(function(){
        log('asyncThing1 seems to be done...');
        dfd.resolve('1111');
        },1000);
        return dfd.promise();
        }
        function asyncThing2(){
        var dfd = $.Deferred();
        setTimeout(function(){
        log('asyncThing2 seems to be done...');
        dfd.resolve('222');
        },1500);
        return dfd.promise();
        }
        function asyncThing3(){
        var dfd = $.Deferred();
        setTimeout(function(){
        log('asyncThing3 seems to be done...');
        dfd.resolve('333');
        },2000);
        return dfd.promise();
        }
        /* do it */
        $.when( asyncThing1(), asyncThing2(), asyncThing3() ).done(function(res1, res2, res3){
        log('all done!');
        log(res1 + ', ' + res2 + ', ' + res3);
        })

        異步列隊一開始沒什么人用(現(xiàn)在也沒有什么人用,概念太抽象了,方法名起得太爛了),于是它只能在內(nèi)部自產(chǎn)自銷。首先被染指的是queue。queue模塊是1.4為吸引社區(qū)的delay插件,特地從data模塊中分化的產(chǎn)物,而data則是從event模塊化分出來的。jQuery新模塊的誕生總是因為用戶對已有API的局限制不滿而致。最早的queue模塊的源碼:
        代碼如下:
        jQuery.extend({
        queue: function( elem, type, data ) {
        if ( !elem ) {
        return;
        }
        type = (type || "fx") + "queue";
        var q = jQuery.data( elem, type );
        // Speed up dequeue by getting out quickly if this is just a lookup
        if ( !data ) {
        return q || [];
        }
        if ( !q || jQuery.isArray(data) ) {
        q = jQuery.data( elem, type, jQuery.makeArray(data) );
        } else {
        q.push( data );
        }
        return q;
        },
        dequeue: function( elem, type ) {
        type = type || "fx";
        var queue = jQuery.queue( elem, type ), fn = queue.shift();
        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
        fn = queue.shift();
        }
        if ( fn ) {
        // Add a progress sentinel to prevent the fx queue from being
        // automatically dequeued
        if ( type === "fx" ) {
        queue.unshift("inprogress");
        }
        fn.call(elem, function() {
        jQuery.dequeue(elem, type);
        });
        }
        }
        });
        jQuery.fn.extend({
        queue: function( type, data ) {
        if ( typeof type !== "string" ) {
        data = type;
        type = "fx";
        }
        if ( data === undefined ) {
        return jQuery.queue( this[0], type );
        }
        return this.each(function( i, elem ) {
        var queue = jQuery.queue( this, type, data );
        if ( type === "fx" && queue[0] !== "inprogress" ) {
        jQuery.dequeue( this, type );
        }
        });
        },
        dequeue: function( type ) {
        return this.each(function() {
        jQuery.dequeue( this, type );
        });
        },
        // Based off of the plugin by Clint Helfers, with permission.
        // http://blindsignals.com/index.php/2009/07/jquery-delay/
        delay: function( time, type ) {
        time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
        type = type || "fx";
        return this.queue( type, function() {
        var elem = this;
        setTimeout(function() {
        jQuery.dequeue( elem, type );
        }, time );
        });
        },
        clearQueue: function( type ) {
        return this.queue( type || "fx", [] );
        }
        });

        1.6添加了_mark,_unmark,promise。queue是讓函數(shù)同屬一個隊伍里面,目的是讓動畫一個接一個執(zhí)行。_mark則是讓它們各自擁有隊伍,并列執(zhí)行(雖然它們只記錄異步列隊中已被執(zhí)行的函數(shù)個數(shù))。promise則在這些并發(fā)執(zhí)行的動畫執(zhí)行后才執(zhí)行另些一些回調(diào)(或動畫)。
        代碼如下:
        (function( jQuery ) {
        function handleQueueMarkDefer( elem, type, src ) {
        //清空記錄deferred個數(shù)的字段,函數(shù)列隊與異步列隊
        var deferDataKey = type + "defer",
        queueDataKey = type + "queue",
        markDataKey = type + "mark",
        defer = jQuery.data( elem, deferDataKey, undefined, true );
        if ( defer &&
        ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
        ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
        // Give room for hard-coded callbacks to fire first
        // and eventually mark/queue something else on the element
        setTimeout( function() {
        if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
        !jQuery.data( elem, markDataKey, undefined, true ) ) {
        jQuery.removeData( elem, deferDataKey, true );
        defer.resolve();
        }
        }, 0 );
        }
        }
        jQuery.extend({
        _mark: function( elem, type ) {
        if ( elem ) {
        type = (type || "fx") + "mark";//創(chuàng)建一個以mark為后綴的字段,用于記錄此列隊中個數(shù)
        jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
        }
        },
        _unmark: function( force, elem, type ) {
        if ( force !== true ) {
        type = elem;
        elem = force;
        force = false;
        }
        if ( elem ) {
        type = type || "fx";
        var key = type + "mark",
        //讓個數(shù)減1,如果第一個參數(shù)為true,就強(qiáng)逼減至0
        count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
        if ( count ) {
        jQuery.data( elem, key, count, true );
        } else {//如果為0,就移除它
        jQuery.removeData( elem, key, true );
        handleQueueMarkDefer( elem, type, "mark" );
        }
        }
        },
        queue: function( elem, type, data ) {
        if ( elem ) {
        type = (type || "fx") + "queue";
        var q = jQuery.data( elem, type, undefined, true );
        // Speed up dequeue by getting out quickly if this is just a lookup
        if ( data ) {
        if ( !q || jQuery.isArray(data) ) {
        q = jQuery.data( elem, type, jQuery.makeArray(data), true );
        } else {
        q.push( data );
        }
        }
        return q || [];
        }
        },
        dequeue: function( elem, type ) {
        type = type || "fx";
        var queue = jQuery.queue( elem, type ),
        fn = queue.shift(),
        defer;
        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
        fn = queue.shift();
        }
        if ( fn ) {
        // Add a progress sentinel to prevent the fx queue from being
        // automatically dequeued
        if ( type === "fx" ) {
        queue.unshift("inprogress");
        }
        fn.call(elem, function() {
        jQuery.dequeue(elem, type);
        });
        }
        if ( !queue.length ) {
        jQuery.removeData( elem, type + "queue", true );
        handleQueueMarkDefer( elem, type, "queue" );
        }
        }
        });
        jQuery.fn.extend({
        queue: function( type, data ) {
        if ( typeof type !== "string" ) {
        data = type;
        type = "fx";
        }
        if ( data === undefined ) {
        return jQuery.queue( this[0], type );
        }
        return this.each(function() {
        var queue = jQuery.queue( this, type, data );
        if ( type === "fx" && queue[0] !== "inprogress" ) {
        jQuery.dequeue( this, type );
        }
        });
        },
        dequeue: function( type ) {
        return this.each(function() {
        jQuery.dequeue( this, type );
        });
        },
        // Based off of the plugin by Clint Helfers, with permission.
        // http://blindsignals.com/index.php/2009/07/jquery-delay/
        delay: function( time, type ) {
        time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
        type = type || "fx";
        return this.queue( type, function() {
        var elem = this;
        setTimeout(function() {
        jQuery.dequeue( elem, type );
        }, time );
        });
        },
        clearQueue: function( type ) {
        return this.queue( type || "fx", [] );
        },
        //把jQuery對象裝進(jìn)一個異步列隊,允許它在一系列動畫中再執(zhí)行之后綁定的回調(diào)
        promise: function( type, object ) {
        if ( typeof type !== "string" ) {
        object = type;
        type = undefined;
        }
        type = type || "fx";
        var defer = jQuery.Deferred(),
        elements = this,
        i = elements.length,
        count = 1,
        deferDataKey = type + "defer",
        queueDataKey = type + "queue",
        markDataKey = type + "mark";
        function resolve() {
        if ( !( --count ) ) {
        defer.resolveWith( elements, [ elements ] );
        }
        }
        while( i-- ) {
        //如果它之前已經(jīng)使用過unmark, queue等方法,那么我們將生成一個新的Deferred放進(jìn)緩存系統(tǒng)
        if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
        ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
        jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
        jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
        count++;
        tmp.done( resolve );
        }
        }
        resolve();
        return defer.promise();
        }
        });
        })( jQuery );

        jQuery.ajax模塊也被染指,$.XHR對象,當(dāng)作HTTPXMLRequest對象的仿造器是由一個Deferred對象與一個_Deferred的對象構(gòu)成。
        代碼如下:
        deferred = jQuery.Deferred(),
        completeDeferred = jQuery._Deferred(),
        jqXHR ={/**/}
        //....
        deferred.promise( jqXHR );
        jqXHR.success = jqXHR.done;
        jqXHR.error = jqXHR.fail;
        jqXHR.complete = completeDeferred.done;

        jQuery1.7,從deferred模塊中分化出callback模塊,其實就是之前的_Deferred的增強(qiáng)版,添加去重,鎖定,return false時中斷執(zhí)行下一個回調(diào),清空等功能。
        代碼如下:
        (function( jQuery ) {
        // String to Object flags format cache
        var flagsCache = {};
        // Convert String-formatted flags into Object-formatted ones and store in cache
        function createFlags( flags ) {
        var object = flagsCache[ flags ] = {},
        i, length;
        flags = flags.split( /\s+/ );
        for ( i = 0, length = flags.length; i < length; i++ ) {
        object[ flags[i] ] = true;
        }
        return object;
        }
        /*
        * Create a callback list using the following parameters:
        *
        * flags: an optional list of space-separated flags that will change how
        * the callback list behaves
        *
        * By default a callback list will act like an event callback list and can be
        * "fired" multiple times.
        *
        * Possible flags:
        *
        * once: will ensure the callback list can only be fired once (like a Deferred)
        *
        * memory: will keep track of previous values and will call any callback added
        * after the list has been fired right away with the latest "memorized"
        * values (like a Deferred)
        *
        * unique: will ensure a callback can only be added once (no duplicate in the list)
        *
        * stopOnFalse: interrupt callings when a callback returns false
        *
        */
        jQuery.Callbacks = function( flags ) {
        // Convert flags from String-formatted to Object-formatted
        // (we check in cache first)
        flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
        var // Actual callback list
        list = [],
        // Stack of fire calls for repeatable lists
        stack = [],
        // Last fire value (for non-forgettable lists)
        memory,
        // Flag to know if list is currently firing
        firing,
        // First callback to fire (used internally by add and fireWith)
        firingStart,
        // End of the loop when firing
        firingLength,
        // Index of currently firing callback (modified by remove if needed)
        firingIndex,
        // Add one or several callbacks to the list
        add = function( args ) {
        var i,
        length,
        elem,
        type,
        actual;
        for ( i = 0, length = args.length; i < length; i++ ) {
        elem = args[ i ];
        type = jQuery.type( elem );
        if ( type === "array" ) {
        // Inspect recursively
        add( elem );
        } else if ( type === "function" ) {
        // Add if not in unique mode and callback is not in
        if ( !flags.unique || !self.has( elem ) ) {
        list.push( elem );
        }
        }
        }
        },
        // Fire callbacks
        fire = function( context, args ) {
        args = args || [];
        memory = !flags.memory || [ context, args ];
        firing = true;
        firingIndex = firingStart || 0;
        firingStart = 0;
        firingLength = list.length;
        for ( ; list && firingIndex < firingLength; firingIndex++ ) {
        if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
        memory = true; // Mark as halted
        break;
        }
        }
        firing = false;
        if ( list ) {
        if ( !flags.once ) {
        if ( stack && stack.length ) {
        memory = stack.shift();
        self.fireWith( memory[ 0 ], memory[ 1 ] );
        }
        } else if ( memory === true ) {
        self.disable();
        } else {
        list = [];
        }
        }
        },
        // Actual Callbacks object
        self = {
        // Add a callback or a collection of callbacks to the list
        add: function() {
        if ( list ) {
        var length = list.length;
        add( arguments );
        // Do we need to add the callbacks to the
        // current firing batch?
        if ( firing ) {
        firingLength = list.length;
        // With memory, if we're not firing then
        // we should call right away, unless previous
        // firing was halted (stopOnFalse)
        } else if ( memory && memory !== true ) {
        firingStart = length;
        fire( memory[ 0 ], memory[ 1 ] );
        }
        }
        return this;
        },
        // Remove a callback from the list
        remove: function() {
        if ( list ) {
        var args = arguments,
        argIndex = 0,
        argLength = args.length;
        for ( ; argIndex < argLength ; argIndex++ ) {
        for ( var i = 0; i < list.length; i++ ) {
        if ( args[ argIndex ] === list[ i ] ) {
        // Handle firingIndex and firingLength
        if ( firing ) {
        if ( i <= firingLength ) {
        firingLength--;
        if ( i <= firingIndex ) {
        firingIndex--;
        }
        }
        }
        // Remove the element
        list.splice( i--, 1 );
        // If we have some unicity property then
        // we only need to do this once
        if ( flags.unique ) {
        break;
        }
        }
        }
        }
        }
        return this;
        },
        // Control if a given callback is in the list
        has: function( fn ) {
        if ( list ) {
        var i = 0,
        length = list.length;
        for ( ; i < length; i++ ) {
        if ( fn === list[ i ] ) {
        return true;
        }
        }
        }
        return false;
        },
        // Remove all callbacks from the list
        empty: function() {
        list = [];
        return this;
        },
        // Have the list do nothing anymore
        disable: function() {
        list = stack = memory = undefined;
        return this;
        },
        // Is it disabled?
        disabled: function() {
        return !list;
        },
        // Lock the list in its current state
        lock: function() {
        stack = undefined;
        if ( !memory || memory === true ) {
        self.disable();
        }
        return this;
        },
        // Is it locked?
        locked: function() {
        return !stack;
        },
        // Call all callbacks with the given context and arguments
        fireWith: function( context, args ) {
        if ( stack ) {
        if ( firing ) {
        if ( !flags.once ) {
        stack.push( [ context, args ] );
        }
        } else if ( !( flags.once && memory ) ) {
        fire( context, args );
        }
        }
        return this;
        },
        // 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 !!memory;
        }
        };
        return self;
        };
        })( jQuery );

        這期間有還個小插曲,jQuery團(tuán)隊還想增加一個叫Topic的模塊,內(nèi)置發(fā)布者訂閱者機(jī)制,但這封裝太溥了,結(jié)果被否決。
        代碼如下:
        (function( jQuery ) {
        var topics = {},
        sliceTopic = [].slice;
        jQuery.Topic = function( id ) {
        var callbacks,
        method,
        topic = id && topics[ id ];
        if ( !topic ) {
        callbacks = jQuery.Callbacks();
        topic = {
        publish: callbacks.fire,
        subscribe: callbacks.add,
        unsubscribe: callbacks.remove
        };
        if ( id ) {
        topics[ id ] = topic;
        }
        }
        return topic;
        };
        jQuery.extend({
        subscribe: function( id ) {
        var topic = jQuery.Topic( id ),
        args = sliceTopic.call( arguments, 1 );
        topic.subscribe.apply( topic, args );
        return {
        topic: topic,
        args: args
        };
        },
        unsubscribe: function( id ) {
        var topic = id && id.topic || jQuery.Topic( id );
        topic.unsubscribe.apply( topic, id && id.args ||
        sliceTopic.call( arguments, 1 ) );
        },
        publish: function( id ) {
        var topic = jQuery.Topic( id );
        topic.publish.apply( topic, sliceTopic.call( arguments, 1 ) );
        }
        });
        })( jQuery );

        雖然把大量代碼移動callbacks,但1.7的Deferred卻一點沒有沒變小,它變得更重型,它由三個函數(shù)列隊組成了。并且返回的是Promise對象,比原來多出了pipe, state, progress, always方法。ajax那邊就變成這樣:
        代碼如下:
        deferred = jQuery.Deferred(),
        completeDeferred = jQuery.Callbacks( "once memory" ),
        deferred.promise( jqXHR );
        jqXHR.success = jqXHR.done;
        jqXHR.error = jqXHR.fail;
        jqXHR.complete = completeDeferred.add;

        queue那邊也沒變多少。
        代碼如下:
        (function( jQuery ) {
        function handleQueueMarkDefer( elem, type, src ) {
        var deferDataKey = type + "defer",
        queueDataKey = type + "queue",
        markDataKey = type + "mark",
        defer = jQuery._data( elem, deferDataKey );
        if ( defer &&
        ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
        ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
        // Give room for hard-coded callbacks to fire first
        // and eventually mark/queue something else on the element
        setTimeout( function() {
        if ( !jQuery._data( elem, queueDataKey ) &&
        !jQuery._data( elem, markDataKey ) ) {
        jQuery.removeData( elem, deferDataKey, true );
        defer.fire();
        }
        }, 0 );
        }
        }
        jQuery.extend({
        _mark: function( elem, type ) {
        if ( elem ) {
        type = ( type || "fx" ) + "mark";
        jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
        }
        },
        _unmark: function( force, elem, type ) {
        if ( force !== true ) {
        type = elem;
        elem = force;
        force = false;
        }
        if ( elem ) {
        type = type || "fx";
        var key = type + "mark",
        count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
        if ( count ) {
        jQuery._data( elem, key, count );
        } else {
        jQuery.removeData( elem, key, true );
        handleQueueMarkDefer( elem, type, "mark" );
        }
        }
        },
        queue: function( elem, type, data ) {
        var q;
        if ( elem ) {
        type = ( type || "fx" ) + "queue";
        q = jQuery._data( elem, type );
        // Speed up dequeue by getting out quickly if this is just a lookup
        if ( data ) {
        if ( !q || jQuery.isArray(data) ) {
        q = jQuery._data( elem, type, jQuery.makeArray(data) );
        } else {
        q.push( data );
        }
        }
        return q || [];
        }
        },
        dequeue: function( elem, type ) {
        type = type || "fx";
        var queue = jQuery.queue( elem, type ),
        fn = queue.shift(),
        hooks = {};
        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
        fn = queue.shift();
        }
        if ( fn ) {
        // Add a progress sentinel to prevent the fx queue from being
        // automatically dequeued
        if ( type === "fx" ) {
        queue.unshift( "inprogress" );
        }
        jQuery._data( elem, type + ".run", hooks );
        fn.call( elem, function() {
        jQuery.dequeue( elem, type );
        }, hooks );
        }
        if ( !queue.length ) {
        jQuery.removeData( elem, type + "queue " + type + ".run", true );
        handleQueueMarkDefer( elem, type, "queue" );
        }
        }
        });
        jQuery.fn.extend({
        queue: function( type, data ) {
        var setter = 2;
        if ( typeof type !== "string" ) {
        data = type;
        type = "fx";
        setter--;
        }
        if ( arguments.length < setter ) {
        return jQuery.queue( this[0], type );
        }
        return data === undefined ?
        this :
        this.each(function() {
        var queue = jQuery.queue( this, type, data );
        if ( type === "fx" && queue[0] !== "inprogress" ) {
        jQuery.dequeue( this, type );
        }
        });
        },
        dequeue: function( type ) {
        return this.each(function() {
        jQuery.dequeue( this, type );
        });
        },
        // Based off of the plugin by Clint Helfers, with permission.
        // http://blindsignals.com/index.php/2009/07/jquery-delay/
        delay: function( time, type ) {
        time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
        type = type || "fx";
        return this.queue( type, function( next, hooks ) {
        var timeout = setTimeout( next, time );
        hooks.stop = function() {
        clearTimeout( timeout );
        };
        });
        },
        clearQueue: function( type ) {
        return this.queue( type || "fx", [] );
        },
        // Get a promise resolved when queues of a certain type
        // are emptied (fx is the type by default)
        promise: function( type, object ) {
        if ( typeof type !== "string" ) {
        object = type;
        type = undefined;
        }
        type = type || "fx";
        var defer = jQuery.Deferred(),
        elements = this,
        i = elements.length,
        count = 1,
        deferDataKey = type + "defer",
        queueDataKey = type + "queue",
        markDataKey = type + "mark",
        tmp;
        function resolve() {
        if ( !( --count ) ) {
        defer.resolveWith( elements, [ elements ] );
        }
        }
        while( i-- ) {
        if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
        ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
        jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
        jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
        count++;
        tmp.add( resolve );
        }
        }
        resolve();
        return defer.promise( object );
        }
        });
        })( jQuery );

        這時候,鉤子機(jī)制其實已經(jīng)在jQuery內(nèi)部蔓延起來,1.5是css模塊的cssHooks,1.6是屬性模塊的attrHooks, propHooks, boolHooks, nodeHooks,1.7是事件模塊的fixHooks, keyHooks, mouseHooks,1.8是queue模塊的_queueHooks,由于_queueHooks,queue終于瘦身了。
        代碼如下:
        View Code?//1.8
        jQuery.extend({
        queue: function( elem, type, data ) {
        var queue;
        if ( elem ) {
        type = ( type || "fx" ) + "queue";
        queue = jQuery._data( elem, type );
        // Speed up dequeue by getting out quickly if this is just a lookup
        if ( data ) {
        if ( !queue || jQuery.isArray(data) ) {
        queue = jQuery._data( elem, type, jQuery.makeArray(data) );
        } else {
        queue.push( data );
        }
        }
        return queue || [];
        }
        },
        dequeue: function( elem, type ) {
        type = type || "fx";
        var queue = jQuery.queue( elem, type ),
        fn = queue.shift(),
        hooks = jQuery._queueHooks( elem, type ),
        next = function() {
        jQuery.dequeue( elem, type );
        };
        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
        fn = queue.shift();
        }
        if ( fn ) {
        // Add a progress sentinel to prevent the fx queue from being
        // automatically dequeued
        if ( type === "fx" ) {
        queue.unshift( "inprogress" );
        }
        // clear up the last queue stop function
        delete hooks.stop;
        fn.call( elem, next, hooks );
        }
        if ( !queue.length && hooks ) {
        hooks.empty.fire();
        }
        },
        // not intended for public consumption - generates a queueHooks object, or returns the current one
        _queueHooks: function( elem, type ) {
        var key = type + "queueHooks";
        return jQuery._data( elem, key ) || jQuery._data( elem, key, {
        empty: jQuery.Callbacks("once memory").add(function() {
        jQuery.removeData( elem, type + "queue", true );
        jQuery.removeData( elem, key, true );
        })
        });
        }
        });
        jQuery.fn.extend({
        queue: function( type, data ) {
        var setter = 2;
        if ( typeof type !== "string" ) {
        data = type;
        type = "fx";
        setter--;
        }
        if ( arguments.length < setter ) {
        return jQuery.queue( this[0], type );
        }
        return data === undefined ?
        this :
        this.each(function() {
        var queue = jQuery.queue( this, type, data );
        // ensure a hooks for this queue
        jQuery._queueHooks( this, type );
        if ( type === "fx" && queue[0] !== "inprogress" ) {
        jQuery.dequeue( this, type );
        }
        });
        },
        dequeue: function( type ) {
        return this.each(function() {
        jQuery.dequeue( this, type );
        });
        },
        // Based off of the plugin by Clint Helfers, with permission.
        // http://blindsignals.com/index.php/2009/07/jquery-delay/
        delay: function( time, type ) {
        time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
        type = type || "fx";
        return this.queue( type, function( next, hooks ) {
        var timeout = setTimeout( next, time );
        hooks.stop = function() {
        clearTimeout( timeout );
        };
        });
        },
        clearQueue: function( type ) {
        return this.queue( type || "fx", [] );
        },
        // Get a promise resolved when queues of a certain type
        // are emptied (fx is the type by default)
        promise: function( type, obj ) {
        var tmp,
        count = 1,
        defer = jQuery.Deferred(),
        elements = this,
        i = this.length,
        resolve = function() {
        if ( !( --count ) ) {
        defer.resolveWith( elements, [ elements ] );
        }
        };
        if ( typeof type !== "string" ) {
        obj = type;
        type = undefined;
        }
        type = type || "fx";
        while( i-- ) {
        if ( (tmp = jQuery._data( elements[ i ], type + "queueHooks" )) && tmp.empty ) {
        count++;
        tmp.empty.add( resolve );
        }
        }
        resolve();
        return defer.promise( obj );
        }
        });

        同時,動畫模塊迎來了它第三次大重構(gòu),它也有一個鉤子Tween.propHooks。它多出兩個對象,其中Animation返回一個異步列隊,Tween 是用于處理單個樣式或?qū)傩缘淖兓喈?dāng)于之前Fx對象。animate被抽空了,它在1.72可是近百行的規(guī)模。jQuery通過鉤子機(jī)制與分化出一些新的對象,將一些巨型方法重構(gòu)掉。現(xiàn)在非常長的方法只龜縮在節(jié)點模塊,回調(diào)模塊。
        代碼如下:
        animate: function( prop, speed, easing, callback ) {
        var empty = jQuery.isEmptyObject( prop ),
        optall = jQuery.speed( speed, easing, callback ),
        doAnimation = function() {
        // Operate on a copy of prop so per-property easing won't be lost
        var anim = Animation( this, jQuery.extend( {}, prop ), optall );
        // Empty animations resolve immediately
        if ( empty ) {
        anim.stop( true );
        }
        };
        return empty || optall.queue === false ?
        this.each( doAnimation ) :
        this.queue( optall.queue, doAnimation );
        },

        到目前為止,所有異步的東西都被jQuery改造成異步列隊的“子類”或叫“變種”更合適些。如domReady, 動畫,AJAX,與執(zhí)行了promise或delay或各種特效方法之后的jQuery對象。于是所有異步的東西在promise的加護(hù)下,像同步那樣編寫異步程序。

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        jquery1.83之前所有與異步列隊相關(guān)的模塊詳細(xì)介紹_jquery

        jquery1.83之前所有與異步列隊相關(guān)的模塊詳細(xì)介紹_jquery:jQuery在1.5引入了Deferred對象(異步列隊),當(dāng)時它還沒有劃分為一個模塊,放到核心模塊中。直到1.52才分割出來。它擁有三個方法:_Deferred, Deferred與when。 出于變量在不同作用域的共用,jQuery實現(xiàn)異步列隊時不使用面向?qū)ο蠓绞?,它把_Deferre
        推薦度:
        標(biāo)簽: 模塊 相關(guān)的 異步
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 成年在线网站免费观看无广告 | 国产老女人精品免费视频| 亚洲精品视频免费看| 久久99热精品免费观看牛牛| 久久精品国产亚洲| 99re在线这里只有精品免费| 亚洲国产精品第一区二区 | 最近2019中文字幕免费看最新| 亚洲国产午夜精品理论片| 我们的2018在线观看免费高清| 亚洲福利电影一区二区?| 91黑丝国产线观看免费| 亚洲啪啪免费视频| 日韩特黄特色大片免费视频| 亚洲高清国产拍精品熟女| 国产免费直播在线观看视频| 四虎永久在线精品免费一区二区| 亚洲熟女乱综合一区二区| 全黄大全大色全免费大片| 亚洲成a人片在线观看播放| 毛片免费观看网址| 成年免费a级毛片| 亚洲AV成人无码久久精品老人| 免费观看无遮挡www的视频| 亚洲欧美日韩中文字幕一区二区三区| 日本高清免费不卡在线| h视频免费高清在线观看| 亚洲AV色香蕉一区二区| 美女视频黄a视频全免费| 免费无码午夜福利片 | 亚洲国产精品一区二区第一页| 亚洲免费视频观看| 狠狠热精品免费观看| 亚洲AV乱码一区二区三区林ゆな | 国产亚洲精品免费视频播放| 亚洲精品国产成人| 亚洲а∨天堂久久精品| 精品一区二区三区无码免费视频| 亚洲乱亚洲乱妇24p| 国产亚洲精品va在线| 在线观看成人免费|