自己实现ES6中的Promise API
Promise API是ES6的推荐标准,该API是由各JavaScript的执行引擎在底层,通常是使用C++语言实现的
为了更好地理解Promise API的使用方法并探究其可能的实现方式,笔者在JavaScript层面对Promise API进行了实现。
该实现只是作为实验、学习使用,虽然与内置的实现功能相同,但是在设计和运行效率上肯定是不能相提并论。
我也希望之后能对自己的实现进行改善。
该实现在处理异步任务时,采用了轮询的方式来检测其状态的变化。
具体代码如下(注:笔者采用Node方式进行模块定义,需要时可以通过Browserify等工具处理成浏览器可用的版本):
"use strict"; const STATUS_PENDING = 'pending', STATUS_FULFILLED = 'fulfilled', STATUS_REJECTED = 'rejected'; const POLL_INTERVAL = 200; function JSPromise(executor){ if(!executor || typeof executor != 'function'){ throw "No executor specified for this promise!"; } var _this = this; this.promiseStatus = STATUS_PENDING; this.resolved = false; this.promiseValue = undefined; this.rejectReason = undefined; this.onFulfilled = undefined; this.onRejected = undefined; function resolve(value){ _this.promiseValue = value; _this.promiseStatus = STATUS_FULFILLED; } function reject(reason){ _this.rejectReason = reason; _this.promiseStatus = STATUS_REJECTED; } executor.apply(this, [resolve, reject]); }; JSPromise.resolve = function(value){ return new JSPromise(function(resolve, reject){ resolve(value); }); }; JSPromise.reject = function(reason){ return new JSPromise(function(resolve, reject){ reject(reason); }); }; JSPromise.prototype.then = function(onFulfilled, onRejected){ if(this.resolved || (!onFulfilled && !onRejected) || (typeof onFulfilled != 'function' && typeof onRejected != 'function')){ return JSPromise.resolve(undefined); } const _this = this; this.onFulfilled = (onFulfilled && typeof onFulfilled == 'function')?onFulfilled: this.onFulfilled; this.onRejected = (onRejected && typeof onRejected == 'function')?onRejected: this.onRejected; if(this.promiseStatus === STATUS_FULFILLED){ this.resolved = true; if(!this.onFulfilled){ return JSPromise.resolve(); } let retVal = this.onFulfilled.apply(this, [this.promiseValue]); if(retVal instanceof JSPromise){ return retVal; }else{ return JSPromise.resolve(retVal); } } if(this.promiseStatus === STATUS_REJECTED){ this.resolved = true; if(!this.onRejected){ return JSPromise.reject(this.rejectReason); } let retVal = this.onRejected.apply(this, [this.rejectReason]); if(retVal instanceof JSPromise){ return retVal; }else{ return JSPromise.resolve(retVal); } } if(this.promiseStatus === STATUS_PENDING){ const _this = this; return new JSPromise(function (resolve, reject){ setTimeout(function checkStatus(){ if(_this.resolved){ resolve(); }else if(_this.promiseStatus === STATUS_FULFILLED && _this.onFulfilled){ _this.resolved = true; let retVal = _this.onFulfilled.apply(_this, [_this.promiseValue]); if(retVal instanceof JSPromise){ retVal.then(function(value){ resolve(value); }); }else{ resolve(retVal); } }else if(_this.promiseStatus === STATUS_REJECTED){ if(_this.onRejected){ _this.resolved = true; let retVal = _this.onRejected.apply(_this, [_this.rejectReason]); if(retVal instanceof JSPromise){ retVal.then(function(value){ resolve(value); }); }else{ resolve(retVal); } }else{ reject(_this.rejectReason); } }else if(_this.promiseStatus === STATUS_PENDING){ setTimeout(function(){ checkStatus(resolve, reject); }, POLL_INTERVAL); }else{ _this.resolved = true; resolve(); } }, 0); }); } throw new Error("Unexpected status: "+_this.promiseStatus); }; JSPromise.prototype.catch = function(onRejected){ if(this.resolved){ return JSPromise.resolve(); } if(!onRejected || typeof onRejected != 'function'){ throw "Must specify an 'onRejected' callback function as the argument!"; } return this.then(undefined, onRejected); }; module.exports = JSPromise;
欢迎批评指正,相互探讨。
本实验的源码和测试代码放置于github:https://github.com/waychan23/promise-js-impl。