Promise的简单实现

ES6 原生提供了 Promise 对象,大大简化了 callback 的代码维护难度。使用promise对象之后可以使用一种链式调用的方式来组织代码;让代码更加的直观。

如果想在老浏览器中使用 Promise,需要使用第三方库。实际实现远离并不复杂,仅需要十几行代码,就能实现类似的效果(实际还是有点区别的)。

代码如下:

// 简单的实现 Promise 的函数
// 原文地址:http://www.miaoqiyuan.cn/p/promise
var PromiseDemo = function(fun, _status_code){
	
	this._status_code = _status_code || 'status';
	
	//执行
	this.run = function(){
		this._result = fun.call(this, fun);
		
		//如果执行函数会 同步 返回结果,则调用callback。
		if( !! this._result ){
			return this.callback();
		};
	};
	
	//回调函数,如果不是立即返回结果,需要手动调用
	this.callback = function(_result){
		
		//异部调用时,传入执行结果
		if( !!_result ){
			this._result = _result;
		}
		
		//如过状态不是 object
		this._result = this._result || {};
		
		//如果没有指定 【返回状态】 值,如果没有,则使用 status
		this._status = this._result[this._status_code] || 'fail';
		
		/*
			如果 【返回状态】 已经定义了 回调函数,调用本状态回调函数
			如果 【返回状态】 没有定义,则调用 _default 函数
			如果 【返回状态】 没有定义,并且没有调用 _default 函数,抛出异常
		*/
		this._callback = this[this._status] || this._default || function(){ throw new Error("Undefined " + this._status); };
		return this._callback.call(this);
	};
	
	//then判断
	this.then = function(_status, callback){
		if( typeof _status == "function" ){
			
			//没有指定状态
			callback = _status;
			if( !('success' in this) ){
				
				//没有 success,则将 callback 设置为 success 状态的回调函数
				_status = 'success';
				
			}else if( !('fail' in this) ){
				
				//没有 fail,则将 callback 设置为 fail 状态的回调函数
				_status = 'fail';
				
			}else{
				
				// 如果 success 和 fail 已经设置,无论调用多少次,都是 默认状态 的回调函数
				_status = '_default';
				
			};
		};
		
		//设置 【返回状态】 的回调函数
		this[_status] = callback;
		
		//链式操作
		return this;
	};
	
	//链式操作
	return this;
}

就这么几行代码,就实现了简单的 Promise。为了方便测试,写成函数

var PromiseTest = function(fun, _status_code, _default){
	if( typeof _status_code == "function" ){
		_default = _status_code;
		_status_code = undefined;
	}
	var pTest = new PromiseDemo(fun, _status_code);
	
	pTest.then(function(){
		console.log("Success!");
		console.log(this._result);
	});
	
	pTest.then(function(){
		console.log("Fail!");
		console.log(this._result);
	});
	
	if( typeof _default == "function"){
		pTest.then(_default);
	};

	return pTest;
}

下面的代码用于测试效果:

返回成功状态

PromiseTest(function(){
	return { status: 'success'};
}).run();
/*
	Success!
	Object {status: "success"}
*/

返回失败状态

PromiseTest(function(){
	return { status: 'fail'};
}).run();
/*
	Fail!
	Object {status: "fail"}
*/

返回其他状态,没有定义,抛出异常

PromiseTest(function(){
	return { status: 'other'};
}).run();
/*
	Uncaught Error: Undefined other(…)
*/

修改 【返回状态】 参数,返回成功状态

PromiseTest(function(){
	return { status: 'other', code : 'success'};
}, "code").run();
/*
	Success!
	Object {status: "other", code: "success"}
*/

增加默认值函数,所有未定义的状态,都是用此回调函数

PromiseTest(function(){
	return { status: 'other'};
}, function(){
	console.log("Other");
}).run();
/*
	Other
*/

自定义状态值,返回 nicai 状态

PromiseTest(function(){
	return { status: 'nicai'};
}).then('wocai', function(){
	console.log("Wocai");
}).then('nicai', function(){
	console.log("Nicai");
}).run();
/*
	Nicai
*/

同步调用有返回值

PromiseTest(function(){
	return { status: 'nicai', value : "abc"};
}).then('nicai', function(){
	console.log("Nicai");
	return this._result.value;
}).run() == 'abc';
/*
	Nicai
	true
*/

异部调用测试:setTimeout

PromiseTest(function(){
	setTimeout(
		(function(){
			this.callback({
				status : 'success'
			});
		}).bind(this),	//必须bind,否则函数内部的 this == window
	1000);
}).run();
/*
	Success!
	Object {status: "success"}
*/

异部调用测试:Ajax

PromiseTest(function(){
	$.ajax({
 		type	: "POST",
		url		: "/services/PinYin",
		data	: {input:'测试'},
		success	: (function(result){
			this.callback({
				status : 'success',
				result : result
			});
		}).bind(this),	//通过 bind 改变 this 的指向
		error	: (function(){
			this.callback();
		}).bind(this)
	});
}).run();

//成功
/*
	Success!
	Object {status: "success", result: "Ceshi"}
*/

//失败
/*
	Fail!
	Object {}
*/

异部调用测试:如果需要用 this 访问 jQuery 的 ajax 对象

PromiseTest(function(){
	var me = this;	//在本函数内,用可以 me 指向 this(PromiseDemo的实例);
	$.ajax({
 		type	: "POST",
		url		: "/services/PinYin",
		data	: {input:'测试'},
		success	: (function(result){
			me.callback({
				status : 'success',
				result : result
			});
		}),
		error	: (function(){
			me.callback();
		})
	});
}).run();

Promise的简单实现》上有1条评论

  1. Pingback引用通告: 使用NodeJS采集老黄历网 | 启源的部落格

发表评论

电子邮件地址不会被公开。 必填项已用*标注