• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題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關鍵字專題關鍵字專題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
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    jquery1.83之前所有與異步列隊相關的模塊詳細介紹_jquery

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

    jquery1.83之前所有與異步列隊相關的模塊詳細介紹_jquery

    jquery1.83之前所有與異步列隊相關的模塊詳細介紹_jquery:jQuery在1.5引入了Deferred對象(異步列隊),當時它還沒有劃分為一個模塊,放到核心模塊中。直到1.52才分割出來。它擁有三個方法:_Deferred, Deferred與when。 出于變量在不同作用域的共用,jQuery實現(xiàn)異步列隊時不使用面向對象方式,它把_Deferre
    推薦度:
    導讀jquery1.83之前所有與異步列隊相關的模塊詳細介紹_jquery:jQuery在1.5引入了Deferred對象(異步列隊),當時它還沒有劃分為一個模塊,放到核心模塊中。直到1.52才分割出來。它擁有三個方法:_Deferred, Deferred與when。 出于變量在不同作用域的共用,jQuery實現(xiàn)異步列隊時不使用面向對象方式,它把_Deferre

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

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

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

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

    jQuery的when方法用于實現(xiàn)回調的回調,或者說,幾個異列列隊都執(zhí)行后才執(zhí)行另外的一些回調。這些后來的回調也是用done, when, fail添加的,但when返回的這個對象已經(jīng)添加讓用戶控制它執(zhí)行的能力了。因為這時它是種叫Promise的東西,只負責添加回調與讓用戶窺探其狀態(tài)。一旦前一段回調都觸發(fā)了,它就自然進入正常回調列隊(deferred ,見Deferred方法的定義)或錯誤回調列隊(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方法的回調就有多少個參數(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);
    });

    如果我們想得到各個異步的結果,我們需要用resolve, resolveWith, reject, rejectWith進行傳遞它們。
    代碼如下:
    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)在也沒有什么人用,概念太抽象了,方法名起得太爛了),于是它只能在內部自產(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í)行另些一些回調(或動畫)。
    代碼如下:
    (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,就強逼減至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對象裝進一個異步列隊,允許它在一系列動畫中再執(zhí)行之后綁定的回調
    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放進緩存系統(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對象,當作HTTPXMLRequest對象的仿造器是由一個Deferred對象與一個_Deferred的對象構成。
    代碼如下:
    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的增強版,添加去重,鎖定,return false時中斷執(zhí)行下一個回調,清空等功能。
    代碼如下:
    (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團隊還想增加一個叫Topic的模塊,內置發(fā)布者訂閱者機制,但這封裝太溥了,結果被否決。
    代碼如下:
    (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īng)在jQuery內部蔓延起來,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 );
    }
    });

    同時,動畫模塊迎來了它第三次大重構,它也有一個鉤子Tween.propHooks。它多出兩個對象,其中Animation返回一個異步列隊,Tween 是用于處理單個樣式或屬性的變化,相當于之前Fx對象。animate被抽空了,它在1.72可是近百行的規(guī)模。jQuery通過鉤子機制與分化出一些新的對象,將一些巨型方法重構掉。現(xiàn)在非常長的方法只龜縮在節(jié)點模塊,回調模塊。
    代碼如下:
    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的加護下,像同步那樣編寫異步程序。

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

    文檔

    jquery1.83之前所有與異步列隊相關的模塊詳細介紹_jquery

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

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国语自产精品视频在线观看| 亚洲七七久久精品中文国产 | 国产精品龙口护士门在线观看 | 人精品影院| 精品欧洲AV无码一区二区男男| 巨大黑人极品VIDEOS精品| 国产精品久久永久免费| 久久亚洲精品成人av无码网站| 蜜桃麻豆www久久国产精品| 国产91在线精品| 欧美精品亚洲精品日韩| 9久久9久久精品| 国产精品丝袜一区二区三区| 亚洲精品二区国产综合野狼| 无码人妻精品一区二| 久久久精品人妻无码专区不卡| 国产精品久久久久久久久久免费| 欧美一卡2卡3卡四卡海外精品| 99热这里只有精品在线| 精品久久久噜噜噜久久久 | 欧美精品在线免费| 久久免费国产精品| 精品视频一区二区三区四区五区| 93精91精品国产综合久久香蕉 | 国产韩国精品一区二区三区久久| 精品久久久久久无码中文字幕一区| 日韩人妻无码精品久久免费一| 亚洲欧美日韩国产精品影院| 污污网站国产精品白丝袜| 日韩精品一区二区三区在线观看| 久久精品二区| 欧美激情精品久久久久久久| 欧美日韩精品在线观看| 亚洲?V无码成人精品区日韩| 日本精品久久久久影院日本| 无码精品第一页| 一区二区国产精品| 日韩精品无码一区二区三区不卡| 久久久久人妻一区精品性色av| 国产精品综合色区在线观看| 国产精品1区2区3区在线播放|