手写Promise基础功能

126 阅读5分钟

写一个Promises来实现Promise功能,当执行resolve()会改变状态,执行then

   const PENDING = 'pending';//进行中
   const FULFILLED = 'fulfilled';//成功
   const REJECTED = 'rejected';//失败
   function Promises(executor) {
       let self = this;
       self.status = PENDING;
       function resolve(value) {
           if (self.status === PENDING) {
               self.status = FULFILLED;//当执行resovle改变状态
               self.value = value;
           }
       }
   
       function reject(reason) {
           if (self.status === PENDING) {
               self.status = REJECTED;//当执行reason改变状态
               self.reason = reason;
           }
       }
	  try {
             executor(resolve, reject);//把改变状态的函数传到函数
          } catch (e) {//当报错会直接执行reject()改变状态
             reject(e);
          }
   }
   Promises.prototype.then=function(onFulfilled,onRejected){
	onFulfilled=typeof onFulfilled==='function'?onFulfilled: value => value;
	onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
        let self=this;
	let Promises2=new Promises(function(resolve,reject){
	if(self.status===FULFILLED){
	      onFulfilled(self.value);//接受状态函数里的返回值
	} 
       })
	return Promises2;
}  
window.Promises = Promises;

原理就是我们在new Promises(function(resolve,reject){ 调用resolve()时,会让Promises状态改变为FULFILLED 这时候then的第一个参数就会触发

var arr=new Promises(function(resolve,reject){
    console.log(123)//123//先执行这个
	resolve();
 });
arr.then(function(value){
console.log(123)//123
})

但是会有问题,看下面代码,因为定时器是异步的当执行到then的时候这时resolve()还没执行,这时的状态还是PENDING,当resolve执行的时候这时代码状态虽然改变了但是self.status已经获取过了,不会执行then

var arr=new Promises(function(resolve,reject){
	setTimeout(function(){//因为定时器是异步的当
	  resolve();
    },10000)								
});
arr.then(function(value){
	 console.log(123)//不会执行then
})

改进代码如下 因为定时器是几秒后执行,这时状态是PENDING,我们把then里的回调push到self.onFulfilled里,当定时器执行完的时候触发resolve()就会把self.onFulfilled里存的then回调函数执行

  const PENDING = 'pending';
  const FULFILLED = 'fulfilled';
  const REJECTED = 'rejected';
   function Promises(executor) {
       let self = this;
       self.status = PENDING;
       self.onFulfilled = [];//成功的回调
       self.onRejected = []; //失败的回调
       //PromiseA+ 2.1
       function resolve(value) {
           if (self.status === PENDING) {
               self.status = FULFILLED;
               self.value = value;
               self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1
           }
       }
   
       function reject(reason) {
           if (self.status === PENDING) {
               self.status = REJECTED;
               self.reason = reason;
               self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2
           }
       }
       try{
          executor(resolve,reject);   
       } catch (e) {
          reject(e);
       }

   }
   
Promises.prototype.then=function(onFulfilled,onRejected){
	onFulfilled=typeof onFulfilled==='function'?onFulfilled: value => value;
	onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
        let self=this;
	let Promises2=new Promises(function(resolve,reject){
		console.log(self.status)
		if(self.status===FULFILLED){
		    try {
                       onFulfilled(self.value);
                    } catch (e) {
                       reject(e);
                     }
		}else if(self.status === REJECTED){
                    try {
                       onRejected(self.reason);
                    } catch (e) {
                       reject(e);
                    }
		}else if (self.status === PENDING){
	         self.onFulfilled.push(() => {
                    try {
                       onFulfilled(self.value)
                    } catch (e) {
                       reject(e);
                    }
                 });
                self.onRejected.push(() => {
                    try {
                    onRejected(self.reason);
                    } catch (e) {
                        reject(e);
                    }
                 });
	}
	})
	return Promises2;
}  

这里我们还没实现链式操作,虽然then里new 了一个新的Promises对象,但是他的状态没有被改变,需要在内部用resolvePromise改变,当第一个Promises对象状态是fulfilled那么后面then创建的对象的状态都是'fulfilled'那么链式操作的then的第一参数函数都能执行,还需要解决当then return的是Promises对象的情况

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promises(executor) {
    let self = this;
    self.status = PENDING;
    self.onFulfilled = [];//成功的回调
    self.onRejected = []; //失败的回调
    //PromiseA+ 2.1
    function resolve(value) {
        if (self.status === PENDING) {
            self.status = FULFILLED;
            self.value = value;
            self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1
        }
    }

    function reject(reason) {
        if (self.status === PENDING) {
            self.status = REJECTED;
            self.reason = reason;
            self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2
        }
    }

    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

Promises.prototype.then = function (onFulfilled, onRejected) {
    //PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
   
    let self = this;
    //PromiseA+ 2.2.7
    let promise2 = new Promises((resolve, reject) => {
		console.log(self.status)
        if (self.status === FULFILLED) {
			
            //PromiseA+ 2.2.2
            //PromiseA+ 2.2.4 --- setTimeout
            setTimeout(() => {
                try {
                    //PromiseA+ 2.2.7.1
                    let x = onFulfilled(self.value);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    //PromiseA+ 2.2.7.2
                    reject(e);
                }
            });
        } else if (self.status === REJECTED) {
            //PromiseA+ 2.2.3
            setTimeout(() => {
                try {
                    let x = onRejected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        } else if (self.status === PENDING) {
            self.onFulfilled.push(() => {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
            self.onRejected.push(() => {
                setTimeout(() => {
                    try {
                        let x = onRejected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
        }
    });
    return promise2;
}

function resolvePromise(promise2, x, resolve, reject) {
    let self = this;
    //PromiseA+ 2.3.1
	
    if (promise2 === x) {
        reject(new TypeError('Chaining cycle'));
    }
    if (x && typeof x === 'object' || typeof x === 'function') {
        let used; //PromiseA+2.3.3.3.3 只能调用一次
        try {
            let then = x.then;
			console.log(then)
            if (typeof then === 'function') {
                //PromiseA+2.3.3
                then.call(x, (y) => {
                    //PromiseA+2.3.3.1
                    if (used) return;
                    used = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, (r) => {
                    //PromiseA+2.3.3.2
                    if (used) return;
                    used = true;
                    reject(r);
                });

            }else{
                //PromiseA+2.3.3.4
                if (used) return;
                used = true;
                resolve(x);
            }
        } catch (e) {
            //PromiseA+ 2.3.3.2
            if (used) return;
            used = true;
            reject(e);
        }
    } else {
        //PromiseA+ 2.3.3.4
        resolve(x);
    }
}
window.Promises=Promises;

当出现then return的是Promises对象的时候,这个时候把return的Promises对象给resolvePromise函数处理,resolvePromise会在内部调用创建的新的Promises对象then方法,如果在新Promises对象里面调用resolve()方法,那么新的对象的then方法内部创建的Promises会被resolvePromise里调用resolve()使状态发生改变,就能实现替换最初的then创建的对象,实现链式操作

	var arr=new Promises(function(resolve,reject){
					resolve();
										
			 });
			 arr.then(function(value){
				return new Promises(function(resolve,reject){//如果return对象会在内部调用then方法
					resolve(123)//调用resolve()方法,会调用then的第一个参数resolvePromise,会让调用then创建的对象的状态变为'fulfilled'
					 console.log(111111)
				})
			 }).then(function(value){//那么后面调用then方法就能执行
				 console.log(value)
			 })

接下来实现catch和finally功能

Promise.prototype.catch

用于指定出错时的回调,是特殊的then方法,catch之后,可以继续 .then

Promise.prototype.finally

不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.

Promise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected);
}

Promise.prototype.finally = function (callback) {
    return this.then((value) => {
        return Promise.resolve(callback()).then(() => {
            return value;
        });
    }, (err) => {
        return Promise.resolve(callback()).then(() => {
            throw err;
        });
    });
}

Promise.all

Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        let index = 0;
        let result = [];
        if (promises.length === 0) {
            resolve(result);
        } else {
            function processValue(i, data) {
                result[i] = data;
                if (++index === promises.length) {
                    resolve(result);
                }
            }
            for (let i = 0; i < promises.length; i++) {
                    //promises[i] 可能是普通值
                    Promise.resolve(promises[i]).then((data) => {
                    processValue(i, data);
                }, (err) => {
                    reject(err);
                    return;
                });
            }
        }
    });
}

Promise.race

Promise.race函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。 如果传的参数数组是空,则返回的 promise 将永远等待。 如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。

Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        if (promises.length === 0) {
            return;
        } else {
            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then((data) => {
                    resolve(data);
                    return;
                }, (err) => {
                    reject(err);
                    return;
                });
            }
        }
    });
}

代码原作者: 作者:刘小夕 链接:segmentfault.com/a/119000001…