zoukankan      html  css  js  c++  java
  • 自己实现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。

  • 相关阅读:
    半同步/半反应堆线程池
    各种排序算法总结
    【面试题】求连续子数组的最大和(三种解法)
    数据结构查找、插入、删除时间复杂度
    红黑树
    opencv 图像基本操作
    plotroc.m
    roc.m
    perfcurve.m
    637. Average of Levels in Binary Tree
  • 原文地址:https://www.cnblogs.com/waychan/p/6666600.html
Copyright © 2011-2022 走看看