`

Queue源码

 
阅读更多

一、queue模块的意义

处理动画事件的回调金字塔。

无queue模块:

$("#animate1").animate({heihgt:"760px"},function(){

        $("#animate2").animate({width:"1280px"},function(){

                  console.log("end");

        });

});

有queue模块:

var fns=[

      function(){$("#animate1").animate({heihgt:"760px"},dequeue},

      function(){$("#animate2").animate({width:"1280px"},dequeue},

      function(){console.log("end")},

]

$(document).queue("animate",fns);

function dequeue(){

      $(document).dequeue("animate")

};

dequeue();

 

二、实现思路

$.queue(ele,type,data)方法:构建Data对象存储queue函数队列data,以type为键附着于ele元素中。

$.dequeue(ele,type)方法:逐个取出queue函数队列并执行。

$._queueHooks(ele,type)方法:构建另一个Data对象hooks。queue函数队列执行完成清空Data对象,该函数存储在hooks.empty中。

queue执行函数传参为next和hooks,以启用下一个queue执行函数(另一种方法是调用dequeue方法逐次执行queue函数)、或者调用hooks中函数,比如$ele.delay调用hooks.stop执行延时等。

注:next函数使用同koa中间件、async,不同于jquery-deferred

 

$ele.queue(type,data)方法:注册、更新或获取queue函数队列,参数data须为数组形式的函数或纯函数。

$ele.dequeue(type)方法:逐次执行queue函数队列。

$ele.clearQueue(type)方法:清空queue函数队列。

$ele.delay(time,type)方法:$ele.queue方法注册queue函数队列时,经过延迟时间time后,调用next执行下一个queue函数。参数time可以是"show","fast",或毫秒数。

$ele.promise(type,obj)方法:返回deferred.promise对象,用以注册done回调函数,该回调函数在各元素的queue函数均执行完成后执行,通过将resolve启动器添加到hooks.empty中实现。

 

三、源码解读

define([
	"./core",
	"./data/var/dataPriv",// 私有对象Data,存储数据或函数
	"./deferred",// 延迟对象Deferred
	"./callbacks"// 回调对象Callbacks
],function(jQuery,dataPriv){

jQuery.extend({
	// 创建、更新或获取Data对象,Data对象通过dataPriv构造函数附着在elem上
	// 结合dequeue方法使用的时候需要保证data为数组形式的函数或函数形式
	// data为queue队列函数回调,参数为next,hooks,dequeue方法中约定
	queue:function(elem,type,data){
		var queue;

		if ( elem ){
			type=(type || "fx")+"queue";
			queue=dataPriv.get(elem,type);// 获取私有Data对象存储数据

			if ( data ){
				if ( !queue || jQuery.isArray(data) ){// 当data为数组格式时,创建、更新或获取私有Data对象
					queue=dataPriv.access(elem,type,jQuery.makeArray(data));
				}else{
					queue.push(data);
				}
			}
			return queue || [];
		}
	},

	// 获取queue方法注册的Data对象,逐个执行queue队列函数,全部执行完成时调用hooks.empty.fire
	// 下一个queue队列函数执行需要在queue方法注册的data中调用next函数参数
	dequeue:function(elem,type){
		type=type || "fx";

		var queue=jQuery.queue(elem,type),// 获取queue方法添加的data数据,可能为函数
			startLength=queue.length,
			fn=queue.shift(),// 获取queue方法添加的data数据首项
			hooks=jQuery._queueHooks(elem,type),
			next=function(){
				jQuery.dequeue(elem,type);
			};

		if ( fn==="inprogress" ){
			fn=queue.shift();
			startLength--;
		}

		if ( fn ){
			// 数组头部添加"inprogress",重用代码考虑;以"fx"作为type值注册的queue队列函数不允许自动执行
			if ( type==="fx" ){
				queue.unshift("inprogress");
			}

			delete hooks.stop;// 为fn创建的hooks.stop腾出空间,但是不执行???
			fn.call(elem,next,hooks);
		}

		// queue方法添加的data数据完毕后,执行_queueHooks注册的回调函数,清空queue模块创建的Data对象
		if ( !startLength && hooks ){
			hooks.empty.fire();
		}
	},

	// 获取或注册回调函数Data对象,附着在elem上
	// 获取后使用Callbacks对象的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对象上,便捷调用
jQuery.fn.extend({
	// 无参数或仅有一个type参数时,获取以type值注册的Data对象数据
	// 有type,没有data时,返回jquery元素对象
	// 既有type又有data时,更新以type值注册的Data数据,并设置hooks回调,
	// type类型为fx,调用$.dequeue执行data首项函数
	queue:function(type,data){
		var setter=2;

		// 处理参数
		if ( typeof type!=="string" ){
			data=type;
			type="fx";
			setter--;
		}

		if ( arguments.length<setter ){// 无参数或仅有一个type参数时
			return jQuery.queue(this[0],type);
		}

		return data===undefined ?
			this :
			this.each(function(){
				var queue=jQuery.queue(this,type,data);

				// 创建hooks存放回调函数,默认包含清空Data对象的empty回调函数,Callbacks的fire方法调用
				jQuery._queueHooks(this,type);

				// type类型为fx,执行queue函数队列首项函数
				if ( type==="fx" && queue[0]!=="inprogress" ){
					jQuery.dequeue(this,type);
				}
			});
	},

	// 调用执行queue方法注册的Data对象数据,即函数队列fn
	dequeue:function(type){
		return this.each(function(){
			jQuery.dequeue(this,type);
		});
	},

	// 清空queue方法注册的Data对象数据
	clearQueue:function(type){
		return this.queue(type || "fx",[]);
	},

	// 当前所有元素的queue队列函数执行完成后(dequeue方法触发执行),执行延迟对象的回调函数
	promise:function(type,obj){
		var tmp,
			count=1,
			defer=jQuery.Deferred(),
			elements=this,
			i=this.length,
			// defer成功时回调启动器,添加到hooks.empty回调中,所有元素的queue函数都执行完成后触发
			resolve=function(){
				if ( !(--count) ){
					defer.resolveWith(elements,[elements]);
				}
			};

		if ( typeof type!=="string" ){
			obj=type;
			type=undefined;
		}
		type=type || "fx";

		while (i--){
			tmp=dataPriv.get(elements[i], type+"queueHooks");
			if ( tmp && tmp.empty ){
				count++;
				tmp.empty.add(resolve);
			}
		}
		resolve();
		return defer.promise(obj);
	}
});

return jQuery;
});

 

define([
	"../core",
	"../queue",
	"../effects" // Delay is optional because of this dependency
],function(jQuery){

// 通过setTimeout函数延迟执行下一个queue队列函数
jQuery.fn.delay=function(time,type){
	time=jQuery.fx ? jQuery.fx.speeds[time] || time : time;// 延迟时间,slow、fast转化为毫秒数
	type=type || "fx";

	return this.queue(type,function(next,hooks){
		var timeout=window.setTimeout(next,time);
		hooks.stop=function(){
			window.clearTimeout(timeout);
		};
	});
};

return jQuery.fn.delay;
});

 

三、源码解读

 

function ff1() {
    console.log(1)
}
function ff2() {
    console.log(2)
}
function succ() {
    console.log('done')
}
$body = $('body')
$body.queue('mx', ff1);
$body.queue('mx', ff2);
 
var promise = $body.promise('mx');
promise.done(succ);
 
setInterval(function() {
    $body.dequeue('mx') // 先弹出1,2,最后是"done"
}, 1500)
 
分享到:
评论

相关推荐

    queue源码分析 c++ vs2019 cpp20 ,包含priority-queue ,未分析,附带上了

    queue源码分析 c++ vs2019 cpp20 ,包含priority-queue ,未分析,附带上了

    Handler Looper MessageQueue 源码解析

    本文将深入解析这三者的源码,帮助你理解它们的工作原理,并教你如何手写一套自己的Handler系统。 首先,我们来了解Handler。Handler是Android中的一个关键类,用于发送和处理消息。在主线程中,一个Handler对象...

    queue源码C++

    让我们深入了解一下`queue`的源码,探讨其主要功能和实现原理。 首先,`queue`包含在`&lt;queue&gt;`头文件中,它是`std`命名空间的一部分。它的主要成员函数有: 1. **构造函数**:默认构造函数创建一个空队列,基于...

    concurrentqueue, 一种快速多消费者多消费者锁空闲并发队列.zip

    concurrentqueue, 一种快速多消费者多消费者锁空闲并发队列 moodycamel::ConcurrentQueue面向 C 的工业强度锁自由队列。注意:如果你只需要一个生产者,单个消费者队列,我有其中的一个太多。特性Knock-your-socks-...

    c#官方线程安全集合源码

    让我们深入探讨其中几个关键的线程安全集合:`ConcurrentBag&lt;T&gt;`, `ConcurrentQueue&lt;T&gt;`, `ConcurrentStack&lt;T&gt;`, 和 `ConcurrentDictionary, TValue&gt;`。 1. **ConcurrentBag** `ConcurrentBag&lt;T&gt;` 是一个线程安全...

    android MessageQueue

    在Android系统中,MessageQueue是消息机制的核心组件之一,它与Handler、Looper紧密协作,用于实现线程间的通信。理解MessageQueue的工作原理对于优化应用程序性能和处理异步操作至关重要。 MessageQueue是一个内部...

    【STL源代码】C++标准库STL源代码下载

    STL,全称为Standard Template ...通过分析源码,我们可以学习到如何平衡空间和时间复杂度,以及如何设计和实现高效的数据结构和算法。这对于任何想要深入理解C++和提升编程能力的人来说都是极其宝贵的学习资源。

    thinkphp5.0.24+queue 队列信息完整源码

    本文将详细探讨在ThinkPHP5.0.24版本中如何使用Queue队列,以及相关源码分析。 一、队列概念与作用 队列是一种先进先出(FIFO)的数据结构,常用于处理批量数据或者需要后台执行的任务,如邮件发送、日志记录、数据...

    开源的消息中间件,包括源码与示例

    In this article, I will introduce a new and independent Open Source Message Queue system that is entirely built in C# and .NET framework 3.5. DotNetMQ is a message broker that has several features ...

    易语言源码易语言Queue队列源码.rar

    通过学习和分析这个"易语言Queue队列源码",开发者可以深入理解易语言的内存管理、数据结构实现以及基本操作的细节。这对于提升编程技能,特别是理解底层数据结构和算法的工作原理非常有帮助。同时,这也为自定义...

    ARM裸奔问题集

    - **源码行号修改**:`#line` 指令可以修改编译器报告错误时显示的源代码行号,有时在处理大型项目时很有帮助。 #### 编译问题与硬件接口 在描述中还提到了一些具体的编译和硬件接口问题,例如LCD显示、NAND Flash...

    TestThread.zip

    本话题将围绕"C++基于无锁线程concurrentqueue实现后台保存图片"这一主题进行详细讲解,结合提供的资源"saveImage实现源码"和"concurrentqueue源码",我们将探讨如何使用无锁队列(concurrentqueue)来优化后台图片...

    C语言头文件 QUEUE.H

    C语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言头文件 QUEUE.HC语言...

    perl-Thread-Queue-3.13-2.module_el8.1.0+229+cd132df8.noarch.rpm

    离线安装包,亲测可用

    libnetfilter_queue

    libnetfilter_queue 这是libnetfilter_queue的生锈绑定,libnetfilter_queue是一个Linux库,该库允许用户空间对数据包的命运进行决策。 注意:除非在装有nfnetlink_queue模块的linux系统上以root身份运行,否则...

    Queue-源码.rar

    本资料“Queue-源码.rar”可能包含一个关于队列实现的开源项目,名为"Queue-master",让我们来深入探讨一下队列及其常见实现。 队列的基本操作包括: 1. 入队(Enqueue):在队尾添加元素。 2. 出队(Dequeue):...

    C队列源代码

    C队列源代码,使用的是模板,template,int size&gt;

    【C++入门到精通】C++入门 - priority-queue(STL)优先队列

    priority_queue 源码

    易语言Queue队列源码

    易语言Queue队列源码通常包含以下几个核心部分: 1. **队列结构定义**:在易语言中,队列的实现可能基于数组或链表。队列的结构体应包括队头和队尾的索引或指针,以及存储元素的容器。例如,如果使用数组,可以定义...

Global site tag (gtag.js) - Google Analytics