jQuery源码05 (3653 , 3797) queue() : 队列方法 : 执行顺序的管理

//对外接口
jQuery.extend({
    queue: function( elem, type, data ) {//入队。元素、队列名字、存进去的函数
    //jQuery.queue( this, type, function( next, hooks ) {})
        var queue;

        if ( elem ) {
            type = ( type || "fx" ) + "queue";//不写队列名字就是fx
            //    $.queue( document , 'q1' , aaa||[aaa,bbb] ); 
            queue = data_priv.get( elem, type );//get方法var cache = this.cache[ this.key( elem ) ];return type === undefined ? cache : cache[ type ];key方法return unlock = elem[ this.expando ];根据元素的唯一标识expando获取在data_priv对象中缓存中的1,2,3,4这个unlock数字,根据unlock这个数字获取cache中的json,根据type获取json中的值
            /*
            data_priv = {
                1(document.203089541586732714850=1):{
                    name(type):'哈哈'(queue),
                    q1queue(type):...(queue数组),
                }
            }
            */

            // Speed up dequeue by getting out quickly if this is just a lookup
            if ( data ) {//函数名
                if ( !queue || jQuery.isArray( data ) ) {//queue没有(函数是不是数组)或者queue有但是函数是数组,注意是数组就会把之前的全部覆盖。
                    /*
                    $.queue( document , 'q1' , aaa ); 
                    $.queue( document , 'q1' , bbb );
                    $.queue( document , 'q1' , [ccc] );
                    */
                    queue = data_priv.access( elem, type, jQuery.makeArray(data) );
                } else {//queue有(说明q1队列之前加过)并且函数不是数组直接push,注意queue没有的时候queue始终存的是一个数组
                    queue.push( data );
                }
            }
            return queue || [];
        }
    },

    dequeue: function( elem, type ) {
        type = type || "fx";
//只能写jQuery.queue(),不能写queue(),queue()是jQuery类的静态方法,只能通过静态方式调用。
/*
jQuery.extend(  {a:function(){alert(1)},b:function(){jQuery.a();}}    )
$.b();
*/
        var queue = jQuery.queue( elem, type ),//得到type对应的值,是一个数组,
            startLength = queue.length,
            fn = queue.shift(),//去除数组第一个
            hooks = jQuery._queueHooks( elem, type ),
            next = function() {
                jQuery.dequeue( elem, type );//下一个,不能直接写dequeue,这行语句还没执行完时dequeue是不存在的
            };

        // If the fx queue is dequeued, always remove the progress sentinel
        if ( fn === "inprogress" ) {
            fn = queue.shift();
            startLength--;
        }

        if ( fn ) {

            // Add a progress sentinel to prevent the fx queue from being
            // automatically dequeued
            if ( type === "fx" ) {
                queue.unshift( "inprogress" );//inprogress添进去
            }

            // clear up the last queue stop function
            delete hooks.stop;
            fn.call( elem, next, hooks );//出队的函数执行,
        }

        if ( !startLength && hooks ) {
            hooks.empty.fire();
        }
    },

    /*
    data_priv = {
        1(elem:document.203089541586732714850=1):{
            name(type):'哈哈'(queue),
            q1queue(type):...(queue数组),
        }
    }
    */
    _queueHooks: function( elem, type ) {
        var key = type + "queueHooks";
        //有就获取,没有key,value都存在value是json就追加
        return data_priv.get( elem, key ) || data_priv.access( elem, key, {
            empty: jQuery.Callbacks("once memory").add(function() {
                data_priv.remove( elem, [ type + "queue", key ] );
            })
        });
    }
});

jQuery.fn.extend({
    //this.queue( type, function( next, hooks ) {
    //$('#div').queue('q1',bbb);
    queue: function( type, data ) {
        var setter = 2;
        //$('#div').queue(bbb);
        if ( typeof type !== "string" ) {//只传了一个函数,没有type
            data = type;
            type = "fx";
            setter--;
        }
///console.log( $('#div').queue('q1') );  查看
        if ( arguments.length < setter ) {
            return jQuery.queue( this[0], type );//静态方法调用
        }

        return data === undefined ?
            this :
            this.each(function() {//$('#div')是一个数组,对每一个设置
                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 );//每一个出队
        });
    },
    
    //.delay(2000)
    /*
    jQuery.fx.speeds = {
        slow: 600,
        fast: 200,
        // Default speed
        _default: 400
    };
    */
    //jQuery.fx = Tween.prototype.init;
    delay: function( time, type ) {
        time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
        type = type || "fx";
//queue第二个参数是匿名函数,也添加进去
        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", [] );//空数组是真
    },
    //队列全部执行完之后,再去调用
    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-- ) {
            tmp = data_priv.get( elements[ i ], type + "queueHooks" );
            if ( tmp && tmp.empty ) {
                count++;
                tmp.empty.add( resolve );
            }
        }
        resolve();
        return defer.promise( obj );
    }
});
原文地址:https://www.cnblogs.com/yaowen/p/6931556.html