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();
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。