zoukankan      html  css  js  c++  java
  • jquery deferred对象解析

    建议先看下callbacks对象的实现
    Deferred 是callbacks 方法的封装调用。开启三个队列实例,分别是resolve,reject,notify。将每个队列开启list.add方法,并且分别指向自己的done、fail、progress

    触发 resolve,reject方法,实际上指向的是callbacks的 fireWith方法,直接触发了队列。所以先使用then方法,加入队列中,然后使用resolve, reject来进行队列的触发,关闭等操作~
    简单调用方法

    var d = new Deferred();
    
    d.then(function(
      console.info('resolve done');
    ),function(){
      console.info('reject fail');
    },funciton() {
      console.info('notify progress);
    });
    
    // ====不能同时触发===可以单个执行===
    // 直接触发done
    d.resolve();
    // fail
    d.reject();
    // pregress
    d.notify();
    

    deferred的中文注解

    jQuery.extend({
    
    	Deferred: function( func ) {
    		var tuples = [
    				// once more 保证添加到队列的,只执行一次,并且一旦add立即触发
    				// action, add listener, listener list, final state
    				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
    				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
    				[ "notify", "progress", jQuery.Callbacks("memory") ]
    			],
    			state = "pending",
    			promise = {
    				state: function() {
    					return state;
    				},
    				always: function() {
    					deferred.done( arguments ).fail( arguments );
    					return this;
    				},
    				then: function( /* fnDone, fnFail, fnProgress */ ) {
    					var fns = arguments;
    					// jQuery.Defered(func()).promise();
    					return jQuery.Deferred(function( newDefer ) {
    						jQuery.each( tuples, function( i, tuple ) {
    							// resolve/reject/notify
    							var action = tuple[ 0 ],
    							// 如果没有fnsi 那么久违undefined
    								fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
    							// deferred[ done | fail | progress ] for forwarding actions to newDefer
    							// deferred['done']() | deferred['fail']() |deferred['progress']() 在下面有定义
    							// 实际上这里的deferred done 指向的是list.add,将done,fail,progress的方法都进行了队列添加
    							deferred[ tuple[1] ](function() {
    								// 直接调用fn方法,得到返回结果(这个returned是deferred对象么?为什么可以调用returned.promise)
    								var returned = fn && fn.apply( this, arguments );
    
    								if ( returned && jQuery.isFunction( returned.promise ) ) {
    									// 将方法扩展到deferred对象实例,然后执行done,fail,progress方法
    									// 实际上是进行了callbacks的add调用,不过进行了区分顺序
    									returned.promise()
    										.done( newDefer.resolve )
    										.fail( newDefer.reject )
    										.progress( newDefer.notify );
    								} else {
    									newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
    								}
    							});
    						});
    						fns = null;
    					}).promise();
    				},
    				// Get a promise for this deferred
    				// If obj is provided, the promise aspect is added to the object
    				// 将promise和obj进行合并
    				promise: function( obj ) {
    					return obj != null ? jQuery.extend( obj, promise ) : promise;
    				}
    			},
    			deferred = {};
    
    		// Keep pipe for back-compat
    		promise.pipe = promise.then;
    
    		// Add list-specific methods
    		// 建立resolve,reject,notify的队列实例,并且对done,fail,progress指向list.add 使其可以对自己的队列进行添加方法
    		jQuery.each( tuples, function( i, tuple ) {
    			// 队列实例
    			var list = tuple[ 2 ],
    				stateString = tuple[ 3 ];
    
    			// promise[ done | fail | progress ] = list.add
    			// 将队列实例的add方法赋值给promise的 resolve/reject/notify
    			// 引用add方法
    			promise[ tuple[1] ] = list.add;
    
    			// Handle state
    			if ( stateString ) {
    				list.add(function() {
    					// state = [ resolved | rejected ]
    					state = stateString;
    
    				// [ reject_list | resolve_list ].disable; progress_list.lock
    				// 执行了异或运算,将列表置为disable,将最后的notify  lock
    				// 0 ^ 1 = 1 
    				// 1 ^ 1 = 0
     				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
    			}
    
    			// deferred[ resolve | reject | notify ]
    			// 组装deferred对象 添加 resolve,reject,notify属性方法
    			deferred[ tuple[0] ] = function() {
    				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
    				return this;
    			};
    			// 组装deferred对象 添加resolveWith,rejectWith,notifyWith对象指向callbacks的FireWire方法
    			// fireWith 是用来拼接list的方法~
    			deferred[ tuple[0] + "With" ] = list.fireWith;
    		});
    
    		// Make the deferred a promise
    		// 组装deferred对象 将promise合并到deferred
    		promise.promise( deferred );
    
    		// Call given func if any
    		//  直接调用该方法~
    		if ( func ) {
    			func.call( deferred, deferred );
    		}
    
    		// All done!
    		// deferred 对象包含了 resolve,reject,notify,resolveWith,rejectWith,notifyWith,pipe,done,fail,progress,state,always,then,promise
    		return deferred;
    	},
    
    	// Deferred helper
    	when: function( subordinate /* , ..., subordinateN */ ) {
    		var i = 0,
    			resolveValues = core_slice.call( arguments ),
    			length = resolveValues.length,
    
    			// the count of uncompleted subordinates
    			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
    
    			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
    			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
    
    			// Update function for both resolve and progress values
    			updateFunc = function( i, contexts, values ) {
    				return function( value ) {
    					contexts[ i ] = this;
    					values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
    					if( values === progressValues ) {
    						deferred.notifyWith( contexts, values );
    					} else if ( !( --remaining ) ) {
    						deferred.resolveWith( contexts, values );
    					}
    				};
    			},
    
    			progressValues, progressContexts, resolveContexts;
    
    		// add listeners to Deferred subordinates; treat others as resolved
    		if ( length > 1 ) {
    			progressValues = new Array( length );
    			progressContexts = new Array( length );
    			resolveContexts = new Array( length );
    			for ( ; i < length; i++ ) {
    				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
    					resolveValues[ i ].promise()
    						.done( updateFunc( i, resolveContexts, resolveValues ) )
    						.fail( deferred.reject )
    						.progress( updateFunc( i, progressContexts, progressValues ) );
    				} else {
    					--remaining;
    				}
    			}
    		}
    
    		// if we're not waiting on anything, resolve the master
    		if ( !remaining ) {
    			deferred.resolveWith( resolveContexts, resolveValues );
    		}
    
    		return deferred.promise();
    	}
    });
    
  • 相关阅读:
    5月27 开通博客啦
    源码编译安装mysql-boost-5.7.16.tar.gz报错分析处理
    MHA实践操作
    (转)MySQL高可用方案MHA的部署和原理
    Mysql利用binlog日志恢复数据操作(转)
    生产环境mysql数据库主从恢复从数据库 -- flush tables with read lock;
    带着问题学习openstack
    openstack的网络模式(转)
    openstack 镜像初始化root登录密码
    openstack placement 组件作用理解
  • 原文地址:https://www.cnblogs.com/osinger/p/6015287.html
Copyright © 2011-2022 走看看