手写promise

面试中经常问道能否自己实现某个api其实如果对其掌握扎实都是 难的;promise主要是通过状态去进行任务的队列管理,规避回调地狱;
自己实现的话首先就是思考promise是什么,都包含那些属性和方法;
state;reject;resolve;then;catch;all;race;
大致搭个架子

	class Promise{
		constructor(){
			this.state = 'pending'
			this.value = ''
		}
		reject(){};
		resolve(){};
		then(){};
		catch(){};
		all(){};
		race(){};
	}

简单核对一下,大致也就这样了
在这里插入图片描述

executor

executor是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。

然后promise有个executor方法,会立即执行添加进去;

   class Promise {
       constructor(e) {
           this.state = 'pending'
           this.value = ''
           this.executor(e)
       }
       executor(e) {
           if(typeof e === 'function'){
           		e( this.resolve.bind(this),this.reject.bind(this))//这里后边捣了不少乱,一开始没绑定this,后来又发现写反了。。。
          	}else{
          		this.state = 'rejected';
   			throw new Error('Promise resolver undefined is not a function')	
   		}
        }
       reject(e) { 
           	if(this.state ==='pending'){
   	        	this.state = 'rejected';
   	        	this.value = e;
   	        	console.log(e)
           	}
      	}
       resolve(e) { 
           if(this.state ==='pending'){
   	        	this.state = 'fulfilled';
   	        	this.value = e;
   	        	console.log(e)
       		}
      	}
       then() { }
       catch(){}
       all() { }
       race() { }
   }
   //测试一下看着没啥问题
   let a = new Promise(function(resolve, reject){
       console.log(111)
       let num = Math.floor(Math.random()*10);
       setTimeout(() => {
           console.log('promise timeout')
           if(num>=5) { 
               resolve('fine')
           }else{
               reject('error')
           };
       }, 1000);
   });

then

添加解决(fulfillment)和拒绝(rejection)回调到当前 promise, 返回一个新的 promise, 将以回调的返回值来resolve.

接受两个参数(onFulfilled, onRejected)都是可选参数,就是一个红鲤鱼与绿鲤鱼的问题
在这里插入图片描述

	then(onFulfilled, onRejected) {
		console.log('then=='+this.state)
	    if (this.state === 'resolved') {
	        if (typeof onFulfilled === 'function') {
	            onFulfilled(this.value);
	        }
	    }
	    if (this.state === 'rejected') {
	        if (typeof onRejected === 'function') {
	            onRejected(this.value);
	        }
	    }
	};

测试时这里的log就先跑出来了,换句话说压根没等异步完成直接就处理了,再调整一下,这里只写了添加了的,要不一贴一大坨脑仁疼

	constructor(e) {
         this.resolvedFun = [];
          this.rejectedFun = [];
      };
	reject(e) {
           this.rejectedFun.map(x => x(e));
     }
     resolve(e) {
           this.resolvedFun.map(x => x(e));
     }
	then(onFulfilled, onRejected) {
            if(this.state==='pending'){
                if (typeof onFulfilled === 'function') {
                    this.resolvedFun.push(onFulfilled);
                }
                if (typeof onRejected === 'function') {
                    this.rejecteddFun.push(onRejected);
                }
            }else{...}
       };

catch

catch就省事多了,本质上和then是一样的,而且只有一个onRejected

	catch(onRejected){
		if (typeof onRejected === 'function') {
			this.rejecteddFun.push(onRejected);
		}
	}

链式调用

连续执行两个或者多个异步操作是一个常见的需求,在上一个操作执行成功之后,开始下一个的操作,并带着上一步操作所返回的结果。我们可以通过创造一个 Promise 链来实现这种需求;then() 函数会返回一个和原来不同的新的Promise:

	then(onFulfilled, onRejected){
		return new Promise()
	}

这里轻敌了。。折腾了俩小时没倒腾出来,又经历了断网没保存的折腾心态有点炸了,仔细翻了下重写了;

如果promise的then方法中函数返回结果是一个promise,会自动执行,并延用他的状态,如果成功将会吧成功的结果向外层的下一个then传递;
如果返回的是一个普通值,那就将这个普通值作为下一次成功的结果

需要做的

  1. 判断成功失败函数返回的结果,也就是判断then中传递的函数的返回结果
  2. 判断是不是promise,如果是promise就采用他的状态
  3. 如果不是promise,直接将结果往下传递

修改之前的代码

	then(onFulfilled, onRejected) {
       return new Promise((resolve, reject) => {
           if (this.state === 'pending') {
               if (typeof onFulfilled === 'function') {
                   this.resolvedFun.push(()=>{onFulfilled(this.value)});
               }
               if (typeof onRejected === 'function') {
                   this.rejectedFun.push(() => { onRejected(this.value) });
               }
           }
           if (this.state === 'resolved') {
               if (typeof onFulfilled === 'function') {
                   let x = onFulfilled(this.value);
                   resolve(x)//把promise的resolve传递给promise2
               }
           }
           if (this.state === 'rejected') {
               if (typeof onRejected === 'function') {
                   let x = onRejected(this.value);
                   reject(x)
               }
           }
       })
   };
   //test
   let a = new Promise((resolve, reject) => {
            resolve()
        })
        a.then(e => { console.log('then1'); return 100 })
        .then(e => { console.log('then2') })
        .then(e => { console.log('then3') })

这基本上就齐活了,但是这个then只能处理普通值,面对promise就无力招架了,需要添加个判断看看是不是promise如果是就then不是再传,并且代码有些冗余了,所以还得继续改

then(onFulfilled, onRejected) {
    let promise2 =  new Promise((resolve, reject) => {//这里修改是因为内部函数this只能取到本身传参有问题
        if (this.state === 'pending') {
            this.resolvedFun.push(()=>{
                //添加trycatch防止抛出异常promise错误
                try {
                    setTimeout(() => {  //修改为异步,否则拿不到promise2
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject)
                    }, 0);
                } catch (err) {
                     reject(err);
                }
            });
            this.rejectedFun.push(() => { 
              ...
            });
        }
        if (this.state === 'resolved') {
                ...   
        }
        if (this.state === 'rejected') {                
                ...
        }
    })
    return promise2
};

然后补充核心的resolvePromise方法,这里可以照猫画虎照葫芦画瓢,这个是瓢,参看2.3
promise A+

	const resolvePromise = (promise2,x,resolve,reject){
		if(promise2 === x){
			return reject(new TypeError('chaining cycle detected for promise#<promise>'))//promiseA+规定
		}
		if(typeof x==='object' && x !== null || typeof x==='function'){
			try{
				let then = x.then;
				if(typeof then === 'function'){
					then.call(x,y=>{resolve(y)},r=>{reject(r)})
				}else{
					resolve(x)
				}
			}catch(e){
				reject(e)
			}
		}else{
			reslove(x)//普通值就把刚刚的处理方式丢过来,直接成功并传递值
		}
	}

至此大功告成

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值