林秀栋的技术博客

设计模式(十八) 等待者模式

//通过监听异步进程,触发未来发生的动作。解决不确定先后顺序的异步逻辑。
var W = function(){
	var dfd = [],		//注册了的等待对象容器
		doneArr = [],	//成功回调方法容器
		failArr = [],		//失败回调方法容器
		slice = Array.prototype.slice,
		that = this;
	var Primise = function(){
		this.resolved = false;	//监控对象是否解决成功状态
		this.rejected = false; 	//监控对象是否解决失败状态
	}
	Primise.prototype = {
		//解决成功
		resolve: function(){
			this.resolve = true;
			if(!dfd.length) return;
			for( 遍历dfd-1到0 ){
				//若有对象没被解决或解决失败
				if(dfd[i] && !dfd[i].resolved || dfd[i].rejected) return;
				//清除监控对象
				dfd.splice(i, 1);
			}
			//回调方法
			_exec(doneArr);
		},
		//解决失败
		reject: function(){
			this.rejected = true;
			if(!dfd.length) return;
			dfd.splice(0);	//清除所有监控对象
			//回调方法
			_exec(failArr);
		}
	}
	//创建监控对象
	that.Deferred = function(){
		return new Primise();
	}
	function _exec(arr){	//回调执行方法
		for( 遍历arr ){
			try{
				arr[i] && arr[i]();
			}catch(e){}
		}
	}
	//监控异步方法,参数:监控对象
	that.when = function(){
		dfd = slice.call(arguments);
		var i = dfd.length;
		for(--i; i >=0; i--){
			//如果不存在监控对象,或者监控对象已被解决,或不是监控对象
			if(!dfd[i] || dfd[i].resolved || dfd[i].rejected || !dfd[i] instanceof Primise)
				dfd.splice(i, 1);	//清理内存,清除当前监控对象
		}
		return that;
	}
	//解决成功回调添加方法
	that.done = function(){
		doneArr = doneArr.concat(slice.call(arguments));
		return that;
	}
	//解决失败回调添加方法
	that.fail = function(){
		failArr = failArr.concat(slice.call(arguments));
		return that;
	}
}

//可用于ajax,定时器等异步操作。
var w = new W();
var first = function(){
	var dtd = w.Deferred();
	setTimeout(function(){
		console.log(‘demo1’);
		dtd.resolve();
	},5000)
}()
var second = function(){
	//…//定时器改为10s,其他差不多
}()
w.when(first, second)	//监听两个
	.done(function(){	//添加成功的回调函数
		console.log(‘success’);
	},function(){
		console.log(‘success again’);
	})
	.fail(function(){	//添加失败的回调函数
		console.log(‘fail’);
	})
//first中的dtd.resolve();改为dtd.reject();可执行失败的回调函数。