zoukankan      html  css  js  c++  java
  • Promise 思考及强化实现

    Promise 思考及强化实现

    标签(空格分隔): ES6 Promise


    本文原创,如需转载请注明出处

    我需要什么

    做了Sudoku项目后,很头疼的问题就是代码维护,很大一部分原因是回调嵌套太多,影响代码的可读性,增加了维护难度,尤其是后端的数据库操作,用nodeJs通常会写许多回调嵌套。这次终于打算揭竿起义。

    第二次修改,废话不多说,直接进入正题
    先看下面这段代码

        function do(){
            //查找数据库
            setTimeout(()=>{
                console.log('收到数据');
                //修改字段,并保存
                setTimeout(()=>{
                    console.log('保存成功')
                    //发送响应给前端
                },1000)
                setTimeout
            },1000)
        }
        do()
    

    模拟了非常简单的一个从前端接受请求到发送响应回到前端的过程,
    这个代码是非常简单的,不过看起来并不是,而且一旦需求更复杂,
    这样风格的代码肯定会让我非常头疼

    我需要的代码风格

    1. 每个异步过程独立成块,不再是嵌套风格
    2. 异步返回结果的处理过程独立于异步过程
    3. 可伸缩,直接扩展异步结果处理过程,并不与之前的混在一起,实现细分,独立成块
    4. 每个异步过程存在依赖

    好吧,发现promise满足我的所有需求,拿来现成用?这一点都不好玩
    ,所以研究了一下promise的用法,下面是我简易的需求说明

    需求说明(参考ES6的实现效果)

    1. 每个promise实例 resolve动作 reject动作
    2. promise实例 then方法注册resolve回调,reject回调
    3. A实例执行完回调,then()会返回一个B实例
    4. B实例跟A一样,同样有 resolve动作 reject动作
    5. 调用B的then()方法同样会注册resolve回调,reject回调
    6. 影响B动作的因素有4个(下面详细讲解)
    7. 有catch同then一样,但是只能注册一个错误回调
    8. a实例如过程上依赖于另外一个b实例,则可被当做其resolve参数传递,并且b实例成功好事滚粗依赖于 a 的状态
    9. 一旦实例状态发生改变,状态不会再改变

    影响B实例的因素

    1.A的resolve回调和reject回调是否有异常抛出

    是:B执行reject动作 否:B执行resolve动作
    

    2.A的reject动作是否有回调

    是:回到1. 、       否:B执行reject动作
    

    3.A的resolve动作是否有回调

    是:回到1           否: B执行resolve动作
    

    4.A的回调中return 另一个promise实例C

    C resolve: B resolve    C reject: B reject
    

    具体实现

    Promise实例所有的属性

    class Promise{
        //构造函数 fn为构建实例的异步过程
        constructor(fn){
            //必须为函数类型
    		if(typeof fn !== 'function') throw new Error('not a function');
    		this.success = [];
    		this.sucArg = null;
    		this.fail = [];
    		this.failArg = null;
    		this.state = 0;
    		this.parent = null;
    		//fork promise分支
    		this.fork = [];
    		//传递的error
    		setTimeout(()=>{
    			fn(myPromise.resolve.bind(this),myPromise.reject.bind(this))	
    		},0);
        }
    }
        
    

    Promise实例的方法,then(),catch()

        //onFulfilled成功处理函数,onRejected滚粗处理函数
        then(onFulfilled,onRejected){
            /*参数格式限制*/
    		let fork = new myPromise(()=>{});
    		if(typeof onFulfilled ==='function'){
    			this.success.push(onFulfilled);
    			fork.forkSuc = onFulfilled;
    		}
    		if(typeof onRejected ==='function'){
    			this.fail.push(onRejected);
    			fork.forkRej = onRejected;
    		} 
    		this.fork.push(fork);
    		return fork;
        }
        catch(onRejected){
            //参数必须函数
    		let fork = new myPromise(()=>{});
    		if(typeof onRejected !=='function') return this;
    		this.fail.push(onRejected);
    		fork.forkRej = onRejected;	
    		this.fork.push(fork);
    		return fork;
        }
    

    Promise静态方法resolve,reject

        static resolve(value){
            if(this.state!==0) return;
    		//参数不是myPromise实例
    		if(value instanceof myPromise){
    			//如参数是一个promise实例
    			value.parent = this;
    			if(value.state===1){
    				//实例状态为成功
    				myPromise.resolve.call(this,value.successArg);
    			}else if(value.state===-1){
    				//实例状态为失败
    				myPromise.reject.call(this,value.failArg);
    			}
    		}else{
    			if(!this.success.length){
    				for(let fn of this.fork){
    					myPromise.resolve.call(fn,value);
    				}
    			}else{
    				this.sucArg = value;
    				let cur = 0;
    				for(let fn of this.success){	if(this.fork.length&&fn===this.fork[cur].forkSuc){
    						let error,preArg,bool;
    						try{
    							preArg = fn(value);
    							if(preArg instanceof myPromise){
    								let index = cur;
    								bool = true;
    								preArg.success.push(()=>{	myPromise.resolve.call(this.fork[index],preArg.sucArg);
    								});
    								preArg.fail.push(()=>{			myPromise.reject.call(this.fork[index],preArg.failArg);
    								})
    							}
    						}catch(err){
    							error = err||null; 
    						}
    						if(!bool){
    							error? myPromise.reject.call(this.fork[cur],error): myPromise.resolve.call(this.fork[cur],preArg);
    						}
    						cur++;
    					}else{
    						fn(value);
    					}
    				}
    			}
    			//当前promise变为fulfilled
    			this.state = 1;
    			//如存在parent,则parent.resolve(value)
    			if(this.parent) myPromise.resolve.call(this.parent,value);
    		}
        }
        static reject(value){
            if(this.state!==0) return;
    		//参数是myPromise实例
    		if(value instanceof myPromise){
    			value.parent = this;
    			myPromise.reject.call(this);
    		}else{
    			if(!this.fail.length){
    				for(let fn of this.fork){
    					myPromise.reject.call(fn,value)
    				}
    			}else{
    				this.failArg = value;
    				let cur = 0;
    				for(let fn of this.fail){
    		if(this.fork.length&&fn===this.fork[cur].forkRej){
    						let error,preArg,bool;
    						try{
    							preArg = fn(value);
    							if(preArg instanceof myPromise){
    								let index = cur;
    								bool = true;
    								preArg.success.push(()=>{	myPromise.resolve.call(this.fork[index],preArg.sucArg);
    								});
    								preArg.fail.push(()=>{	myPromise.reject.call(this.fork[index],preArg.failArg);
    								})
    							}
    						}catch(err){
    							error = err||null; 
    						}
    						if(!bool){
    							error? myPromise.reject.call(this.fork[cur],error): myPromise.resolve.call(this.fork[cur],preArg);
    						}
    						cur++;
    					}else{
    						fn(value);
    					}	
    				}
    			}
    			this.state = -1;
    
    			if(this.parent) myPromise.reject.call(this.parent,value);
    		}
            
        }
    

    好了,就这么多,这是个简易的Promise实现,如有错误,或者什么建议
    QQ:387857274欢迎讨论

  • 相关阅读:
    307. Range Sum Query
    OLI 课程 & Java入学考试的五道题
    745. Prefix and Suffix Search 查找最大index的单词
    38.Count and Say 报数
    721. Accounts Merge合并电子邮件账户
    265. Paint House II 房子涂色K种选择的版本
    【转】如何做人性化的代码审查?从高到低、用例子
    java之struts2之文件下载
    java之struts2之文件上传
    java之struts2之拦截器
  • 原文地址:https://www.cnblogs.com/ZxrGloria/p/5727526.html
Copyright © 2011-2022 走看看