ES6 原生提供了 Promise 对象,大大简化了 callback 的代码维护难度。使用promise对象以后能够使用一种链式调用的方式来组织代码;让代码更加的直观。ajax
若是想在老浏览器中使用 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();