Promise实现

125 阅读5分钟

1、Promise的声明

  • 根据 new Promise((resolve,reject)=>{}) ,所以传入一个参数(函数),并且传入就执行---executor

  • executor里面有两个参数,分别为resolve(成功),reject(失败)。

class Promise{
	// 构造器
    constructor(executor){
    	// 成功
    	let resolve = () => {};
        // 失败
        let reject = () => {};
		// 立即执行
		executor(resolve, reject);
    }
}

2、解决基本状态

  • Promise存在三个状态,pending(等待状态-初始状态)、fulfilled(成功状态)、rejected(失败状态)
  • 成功时,new Promise((resolve, reject) => {resolve(value)}),接收参数value,状态由pending转为fulfilled,不可再次改变。
  • 失败时,new Promise((resolve, reject) => {reject(reason)}),接收参数reason,状态由pending转为rejected,不可再次改变。
  • executor函数报错,直接执行reject()
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class Promise{
	// 构造器
    constructor(executor){
    	// 初始化state为等待状态
        this.state = PENDING
        // 成功的值
        this.value = value
        // 失败的原因
        this.reason = reason
    	// 成功
    	let resolve = (value) => {
        	// state改变,resolve调用就会失败
        	if(this.state = PENDING){
            	// resolve调用成功,更改状态
            	this.state = FULFILLED;
                // 存储成功的值
                this.value = value
            }
        };
        // 失败
        let reject = (reason) => {
        	if(this.state = PENDING){
            	this.state = REJECTED
                this.reason = reason
            }
        };
		// 如果executor执行报错,立即执行reject
        try{
        	executor(resolve, reject);
        } catch (err){
        	reject(err)
        }
    }
}

3、then方法

then方法里面有两个参数:onFulfilled,onRejected,成功有成功值,失败有失败原因。

  • 当状态state为fulfilled,则执行onFulfilled,传入this.value。当状态state为rejected,则执行onRejected,传入this.reason
  • onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value活reason依次作为他们的第一个参数
class Promise{
	// 构造器
    constructor(executor){...}
    // then 方法 两个参数
    then(onFulfilled, onRejected){
    	// 成功
    	if(this.state === FULFILLED){
        	onFulfilled(this.value)
        }
        // 失败
        if(this.state === REJECTED){
        	onRejected(this.reason)
        }
    }
}

4、解决异步实现

  • 当resolve在setTimeout内执行,then时state还是pending等待状态,我们就需要在then调用的时候,将成功和失败存到各自的数组中,一旦reject或者resolve,就调用它们

  • 成功或者失败时,forEach调用它们

class Promise{
	constructor(executor){
    	this.state = PENDING;
        this.value = value;
        this.reason = reason;
        // 成功存放的数组
        this.onResolvedCallbacks = [];
        // 失败存放的数组
        this.onRejectedCallbacks = [];
        let resolve = value => {
        	if(this.state === PENDING){
            	this.state === FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        let resolve = value => {
        	if(this.state === PENDING){
            	this.state === REJECTED;
                this.reason = reason;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        try{
        	executor(resolve, reject);
        } catch (err) {
        	reject(err)
        };    
    }
	then(onFulfilled, onRejected){
        if(this.state === FULFILLED){
            onFulfilled(this.value)
        }
        if(this.state === REJECTED){
            onRejected(this.reason)
        }
        // 当状态为pending 时
        if(this.state === PENDING){
            // onFulfilled传入到成功数组
            this.onResolvedCallbacks.push(() => {
                onFulfilled(this.value)
            })
            // onRejected传入到失败数组
            this.onRejectedCallbacks.push(() => {
                onRejected(this.value)
            })
        }
    }
}

5、解决链式调用

new Promise().then().then(),这既是链式调用,用来解决回调地狱

  • 要达到链式调用,then里需要返回一个新的promise。例如:promise2 = new Promise((resolve, reject) => {})。
    • 将这个promise2返回的值传递到下一个then。
    • 如果返回的是一个普通的值,则将普通的值传递给下一个then。
class Promise{
	constructor(executor){
    	this.state = PENDING;
        this.value = value;
        this.reason = reason;
        // 成功存放的数组
        this.onResolvedCallbacks = [];
        // 失败存放的数组
        this.onRejectedCallbacks = [];
        let resolve = value => {
        	if(this.state === PENDING){
            	this.state === FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        let resolve = value => {
        	if(this.state === PENDING){
            	this.state === REJECTED;
                this.reason = reason;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        try{
        	executor(resolve, reject);
        } catch (err) {
        	reject(err)
        };
    }
    then(onFulfilled, onRejected){
        // 声明返回promise2
        let promise2 = new promise((resolve,reject) => {
            if(this.state === FULFILLED){
                let x = onFulfilled(this.value// resolvePromise 函数,处理自己return的promise
                // 和默认的promise2的关系
                resolvePromis(promise2, x, resolve, reject)
            }
            if(this.state === REJECTED){
                let x = onRejected(this.reason)
                resolvePromis(promise2, x, resolve, reject)
            }
            // 当状态为pending 时
            if(this.state === PENDING){
                // onFulfilled传入到成功数组
                this.onResolvedCallbacks.push(() => {
                    let x = onFulfilled(this.value)
                    resolvePromis(promise2, x, resolve, reject)
                })
                // onRejected传入到失败数组
                this.onRejectedCallbacks.push(() => {
                    let x = onRejected(this.value)
                    resolvePromis(promise2, x, resolve, reject)
                })
            }
            // 返回promise,完成链式
            return promise2
        })
    }
}

6、完成resolvePromise函数

让不同的promise代码相互套用,叫做resolvePromise

  • x不能等于promise2,否则会造成循环引用。
  • x不能是null
  • x是对象或者函数(包含promise),let then = x.then。如果取then报错,则走reject()
  • 如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调。如果成功的回调还是promise,就继续递归解析。
  • 成功和失败只能调用一个,所以设定一个called来防止多次调用。
function resolvePromise(promise2, x, resolve, reject){
	// 循环引用报错
    if(x === promise2){
    	return reject(new TypeError('Chaining cycle deteced for promise'))
    }
    // 防止多次调用
    let called
    // x不是null,并且x是对象或者函数
    if(x != null && (typeof x === 'object' || typeof x === 'function')){
    	try {
        	//  promise A+规范,声明 then = x.then方法
            let then = x.then;
            // 如果then是函数,就默认是promise了
            if(typeof then === 'promise'){
            	then.call(x, y => {
                	// 成功和失败只能调用一个
                    if(called) return;
                    called = true;
                    // resolve的结果依旧是promise 那就继续解析
                    resolvePromise(promise2, y, resolve, reject)
                }, err => {
                	// 成功和失败只能调用一个
                    if(called) return;
                    called = true;
                    reject(err);
                })
            } else {
            	resolve(x)
            }
        } catch(e) {
        	if(called) return;
            called = true;
            // 取then出错了那就不要在继续执行了
            reject(e);
        }
    } else {
    	resolve(x);
    }
}

7、解决其他问题

onFulfilled,onRejected都是可选参数,如果他们不是函数,必须被忽略

  • onFulfilled返回一个普通的值,成功时直接等于value => value
  • onRejected返回一个普通值,失败时如果直接等于value => value,则会跑到下一个then中的onFulfilled中,所以直接扔出一个错误,reason => throw err

onFulfilled或onRejected不能同步被调用,必须异步调用,可以用setTimeout解决。

如果onFulfilled或onRejected报错,则这接返回reject()

class Promise{
	constructor(executor){
    	this.state = PENDING;
        this.value = value;
        this.reason = reason;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];
        let resolve = value => {
        	if(this.state === PENDING){
            	this.state === FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        let resolve = value => {
        	if(this.state === PENDING){
            	this.state === REJECTED;
                this.reason = reason;
                this.onResolvedCallbacks.forEach(fn => fn());
            }
        };
        try{
        	executor(resolve, reject);
        } catch (err) {
        	reject(err)
        };
    }
    then(onFulfilled, onRejected){
        //onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        //onRejected如果不是函数,就忽略onRejected,直接扔出错误
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason};
       	let promise2 = new Promise((resolve, reject) = > {
            if(this.state === FULFILLED){
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e){
                        reject(e)
                    }
                },0)
            }
            if(this.state === REJECTED){
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e){
                        reject(e)
                    }
                },0)
             }
            // 当状态为pending 时
            if(this.state === PENDING){
                // onFulfilled传入到成功数组
                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e){
                            reject(e)
                        }
                    },0)
                })
                // onRejected传入到失败数组
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e){
                            reject(e)
                        }
                    },0)
                })
            }
        })
        return promise2;
    }
}

8、catch、resolve、reject、race、all方法

catch方法

class Promise{
	// 构造器
    constructor(executor){...}
    // then 方法 两个参数
    then(onFulfilled, onRejected){...}
    // catch 方法
    catch(fn){
    	return this.then(null,fn)
    }
}

resolve方法

	Promise.resolve = function(val){
    	return new Promise((resolve, reject) => {
        	resolve(val)
        })
    }

reject方法

	Promise.reject = function(val){
    	return new Promise((resolve, reject) => {
        	reject(val)
        })
    }

race方法

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

all方法

获取所有的promise,都执行then,把结果放到数组,一起返回

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