jQuery 队列

Posted by franki on June 12, 2019

队列是一种特殊的线性表,是一种先进先出的机制,把其想象成排队的场景即可。

jQuery中队列入队

queue: function(elem, type, data) {
    var queue;

    if (elem) {
        type = (type || 'fx') + 'queue';
        queue = dataPriv.get(elem, type);

        // Speed up dequeue by getting out quickly if this is just a lookup
        if (data) {
            if (!queue || Array.isArray(data)) {
                queue = dataPriv.access(
                    elem,
                    type,
                    jQuery.makeArray(data)
                );
            } else {
                queue.push(data);
            }
        }
        return queue || [];
    }
},

入队的时候会判断queue是否存在,若是第一次入队,会把对应的回调函数存储在元素上,作为缓存,下次进来的时候只需要简单的push操作即可(queue.push)。说白了就是data与jQuery之间通过了uuid建立了一个无耦合的映射关系,这就涉及到之前文章cache的知识了。

jQuery队列出队

dequeue: function(elem, type) {
    type = type || 'fx';

    var queue = jQuery.queue(elem, type),
        startLength = queue.length,
        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();
        startLength--;
    }

    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 (!startLength && hooks) {
        hooks.empty.fire();
    }
},

_queueHooks: function(elem, type) {
    var key = type + 'queueHooks';
    return (
        dataPriv.get(elem, key) ||
        dataPriv.access(elem, key, {
            empty: jQuery.Callbacks('once memory').add(function() {
                dataPriv.remove(elem, [type + 'queue', key]);
            })
        })
    );
}

从上面的源码可以看出,jQuery.queue既可以用来存储缓存数据,还可以用来获取队列数据,通过queue.shift(),来获取一个回调函数, fn.call(elem, next, hooks)来执行回调函数,并且把next,hooks,传递给外面使用,其中next是下个队列中下一个子项(fn)要执行的函数,hooks是callbacks相关函数。

jQuery队列的源码其实很少,也比较好分析。