手动实现简单的Promise及其基础功能

一、Promise期约函数基本使用

function Ran(){
	return new Promise((resolve, reject) => {
		setTimeout(() => {
			let ranDomNum = Math.random();	
			// 模拟可能成功或者失败的异步任务
			ranDomNum > 0.5 ? resolve('成功') : reject('失败');
		}, 1000);
	})
}

Ran().then(
	data => Ran()
).then(
	value => console.log(value)
).catch(err => console.error(err));

// 成功

// or

// 失败

二、手动实现Promise基础功能

实现思路

1 声明方式

因为在引用Promise时我们使用的是new关键字,所以我们在实现时可以采用构造函数或者class类的实现方式。

  • 代码
class MyPromise{
	constructor(){
	}
}

// 使用commonjs暴露模块
module.exports = MyPromise;
  • 测试
const MyPromise = require('./myPromise');

function Text(){
	return new MyPromise((resolve, reject) => {
		setTimeout(() => {
			let ranDomNum = Math.random();	
			// 模拟可能成功或者失败的异步任务
			ranDomNum > 0.5 ? resolve('成功') : reject('失败');
		}, 1000)
	});
}

Text()

2 实现简单的resolve和reject

  • 设置状态与添加函数

因为promise有三种状态,所以需要设置对应的三个状态(pending, fulfilled, rejected)。当调用promise时我们需要传入一个函数并接收两个函数参数(resolve, reject),这两个函数在外部调用

class MyPromise{
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    constructor(stateFun) {
            /* 
                这里使用bind绑定在promise外部执行的函数this
                避免因为在函数外执行时, 方法内部this指向改变而无法方法内部变量
                
                不能使用call方法绑定this指向
                stateFun.call(this.resolve, this.reject);
                
                因为这里改变的是外部函数被调用时所在作用域的this,如果想要执行不出问题必须使用
                function声明的函数,并且调用resolve与reject时也要使用call来改变指向

                new MyPromise(
                    (resolve, reject) => {
                        let num = Math.random();
                        num > 0.5 ?
                            resolve('成功')
                            : reject('失败');
                    }
                )

            */
			// stateFun函数接收两个函数参数,对应接收成功/失败的结果
            stateFun(this.resolve.bind(this), this.reject.bind(this));
    }
}
  • 添加resolve,reject

当得到对应的期约结果后,会调用对应的成功/失败调用
另外每次实例一个期约时都应该创建一个对应的状态#status, 当得到成功的调用时,resolve函数时意味着已经得到了成功结果,这时应该将状态#status变更为成功(fulfilled),并保存此时的成功结果(使用#data保存,用于then方法的调用返回),当得到失败的调用时,reject方法被调用,在触发reject调用的过程中#status状态变更为拒绝,并保存当前错误的结果,用于then方法的失败回调

class MyPromise {
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    // Promise初始为待定状态
    #status = this.#PENDING;

    // 保存数据结果
    data = null;

    constructor(stateFun) {
            stateFun(this.resolve.bind(this), this.reject.bind(this));
    }
    
    reject(result) {
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;

            // 改变promise状态为失败
            this.#status = this.#REJECTED;

            // 保存失败值
            this.data = result;
    }

    resolve(result) {
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;
            // 改变promise状态为成功
            this.#status = this.#FULFILLED;
            // 保存成功值
            this.data = result;
    }
}

3 实现简单then方法

当得到resolve,reject结果时,调用的then方法要根据#status的状态调用对应的then回调,注意then中某个回调没有传递的情况,还有在实例化promise是直接抛出错误的情况。

class MyPromise {
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    // 保存尚未得到fulfilled状态的then中的函数
    #resolveCallback = [];
    // 保存尚未得到rejected状态的then中的函数
    #rejectCallback = [];

    // Promise初始为待定状态
    #status = this.#PENDING;

    // 保存数据结果
    data = null;

    constructor(stateFun) {

        // 执行传入的异步函数
        // 使用trycatch捕获
        // 实现了原生中(resolve,reject)=>{}中直接抛出错误时,也会返回触发reject
        try {

            stateFun(this.resolve.bind(this), this.reject.bind(this));

        } catch (error) {
            // 指向错误则调用错误方法
            this.reject(error);
        }
    }

    reject(result) {
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;

            // 改变promise状态为失败
            this.#status = this.#REJECTED;

            // 保存失败值
            this.data = result;

            // 在得到结果后将then的参数函数遍历并且执行
            this.#rejectCallback.forEach(callBack => {
                callBack(result);
            });
    }

    resolve(result) {
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;
            // 改变promise状态为成功
            this.#status = this.#FULFILLED;
            // 保存成功值
            this.data = result;

            this.#resolveCallback.forEach(callBack => {
                callBack(result);
            });
    }

    then(onFulfilled, onRejected) {

        /*
        当传入的then回调函数为空时,创建对应的空函数,
        实现了原生中then方法某一项不传,也能不影响执行
    */

        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { };

        onRejected = typeof onRejected === 'function' ? onRejected : () => { };

        /* 
            当外部调用then方法时,会接收两个参数(函数),分别用于处理成功的数据和拒绝的结果
        检测当前promise的状态值,并进入对应的函数中执行得到结果
        */
        if (this.#status == this.#FULFILLED) {// 状态为成功
            //	执行then中成功的回调
            onFulfilled(this.data);
        } else if (this.#status === this.#REJECTED) {// 状态为拒绝
            //	执行then中拒绝的回调
            onRejected(this.data);
        } else if (this.#status === this.#PENDING) {// 状态为待定

            /* 
                这里使用数组接收的是未得到结果的函数

                为什么要添加金数组? 我们有时候会遇到一种情况,当resolve,reject没有得到结果,
                那么在执行then方法时,因为#status未改变(pending),所以不能及时去调用对应的回调
                ,这会导致什么也得不到。所以我们需要将这些没有得到结果的then中的函数放入到待执行的数组,
                当resolve,reject得到结果后将其遍历执行。
                这样就避免了then的时候拿不到结果了。。。
            */

            this.#resolveCallback.push(onFulfilled);

            this.#rejectCallback.push(onRejected);
        }
    }
}

4 添加异步

执行以上函数的时候初看似乎没有什么问题,但是我们添加上执行顺序就可以发现问题

  • 原生
console.log('======1=====');

function isRandom() {
    console.log('=========3=========');
    return new Promise(

        (resolve, reject) => {

            let num = Math.random();

            console.log('=====4====' + num);

            setTimeout(() => {
                num > 0.5 ?
                    resolve('成功')
                    : reject('失败');

                console.log('======5======');
            }, 1000)

        }
    );
}

isRandom().then(

    data => {
        console.log('6---data: ' + data);
    },

    err => console.error('6---err:' + err)

)

console.log('=======2======');

// ======1=====
// =========3=========
// =====4====0.8856507962969764
// =======2======
// ======5======
// 6---data: 成功

手动实现

console.log('======1=====');
function isRandom() {
    console.log('=========3=========');
    return new MyPromise(
        (resolve, reject) => {
            let num = Math.random();
            console.log('=====4====' + num);
            setTimeout(() => {
                num > 0.5 ?
                    resolve('成功')
                    : reject('失败');

                console.log('======5======');
            }, 1000)
        }
    );
}

isRandom().then(

    data => {
        console.log('6---data: ' + data);
    },

    err => console.error('6---err:' + err)

)

console.log('=======2======');

// ======1=====
// =========3=========
// =====4====0.3755981280479803
// =======2======
// 6---err:失败
// ======5======

了解出现这种情况的原因我们先要知道原生代码的执行顺序
1 先执行同步 输出 ‘= = = = 1 = = = =’
2 执行函数 输出 ‘ = = = = 3 = = = = ’
3 执行promise函数内部的函数输出 ‘= = = = 4 = = = =’
4 遇到定时器异步任务
5 执行then then方法是异步的,挂入异步
6 执行 同步输出 ‘= = = = 2 = = = =’
1s后 执行定时器
7 定时器内输出 ‘= = = = 5 = = = = ’
因为resolve, reject是异步的,所以应该先输出 5, 然后触发then方法内的回调
8 输出 ‘= = = = 6 = = = = ’

综上,因为原生中的then,resolve,reject异步任务才有正确的执行结果,所以我们应该给手动实现的代码添加上异步

class MyPromise {
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    // 保存尚未得到fulfilled状态的then中的函数
    #resolveCallback = [];
    // 保存尚未得到rejected状态的then中的函数
    #rejectCallback = [];

    // Promise初始为待定状态
    #status = this.#PENDING;

    // 保存数据结果
    data = null;

    constructor(stateFun) {

        // 执行传入的异步函数
        // 使用trycatch捕获
        // 实现了原生中(resolve,reject)=>{}中直接抛出错误时,也会返回触发reject
        try {

            stateFun(this.resolve.bind(this), this.reject.bind(this));

        } catch (error) {
            // 指向错误则调用错误方法
            this.reject(error);
        }
    }

    reject(result) {
         setTimeout(()=>{
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;

            // 改变promise状态为失败
            this.#status = this.#REJECTED;

            // 保存失败值
            this.data = result;

            // 在得到结果后将then的参数函数遍历并且执行
            this.#rejectCallback.forEach(callBack => {
                callBack(result);
            });
		})
    }

    resolve(result) {
        setTimeout(()=>{
          	// 因为状态不可逆所以需要检测状态是不是待定
           if (this.#status !== this.#PENDING) return;
           // 改变promise状态为成功
           this.#status = this.#FULFILLED;
           // 保存成功值
           this.data = result;

           this.#resolveCallback.forEach(callBack => {
               callBack(result);
           });
         });
    }

    then(onFulfilled, onRejected) {
			 	onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { };
        		onRejected = typeof onRejected === 'function' ? onRejected : () => { };

	        if (this.#status == this.#FULFILLED) {// 状态为成功
	        	setTimeout(()=>{
	            	//	执行then中成功的回调
	            	onFulfilled(this.data);
	            });
	        } else if (this.#status === this.#REJECTED) {// 状态为拒绝
	            setTimeout(()=>{
 					//	执行then中拒绝的回调
	            	onRejected(this.data);
				})
	        } else if (this.#status === this.#PENDING) {// 状态为待定
	            setTimeout(()=>{
					this.#resolveCallback.push(onFulfilled);
	            	this.#rejectCallback.push(onRejected);
				})
	        }
    }
}

// 注意 then 方法中的异步最好是在得到期约结果之后再设置

到这里简单的promise功能已经实现,已经可以完成期约功能。

但是还差一个重要的功能,then的链式调用, 它是期约函数的核心。。。


5 then链式调用

实现(省略resolve, reject, constuctor)

then方法需要返回一个promise对象,当之前的then方法的回调触发后,我们都应该接收并进行判断,判断then方法回调内返回值的类型,如果为非promise则直接使用then方法的返回promise的res直接返回,如果是promise则将其调用then继续执行(结合代码理解),另外要注意then中pending状态中的处理

class MyPromise {
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    // 保存尚未得到fulfilled状态的then中的函数
    #resolveCallback = [];
    // 保存尚未得到rejected状态的then中的函数
    #rejectCallback = [];

    // Promise初始为待定状态
    #status = this.#PENDING;

    // 保存数据结果
    data = null;

		········
		
    then(onFulfilled, onRejected) {
    	/*
			then方法会返回一个新的promise对象,以便使用then方法接收结果
		*/
        let promise = new MyPromise((resolve, reject) => {

            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { };

            onRejected = typeof onRejected === 'function' ? onRejected : () => { };

            /* 
            	添加异步是为了实现不阻塞同步代码的执行,指向返回结果时将函数放在异步中执行就可以
            */
            if (this.#status == this.#FULFILLED) {
                setTimeout(() => {
                    try {
                        // 执行then的成功回调函数,得到返回的结果
                        let callbackValue = onFulfilled(this.data);

                        /*
                        	 判断返回的是否是promise,方法定义在下面,这里的resolve,reject是
                        	 返回的新promise的成功/失败的接收函数
                        */ 
                        this.#isPromise(callbackValue, resolve, reject);
                    } catch (error) {
                    	// 如果出现错误册将其作为reject返回
                        reject(error);
                    }
                })
            } else if (this.#status === this.#REJECTED) {
                setTimeout(() => {
                    try {
                        // 执行then的失败回调 --- 与resolve同理
                        let callbackValue = onRejected(this.data);

                        // 判断返回的是否是promise
                        this.#isPromise(callbackValue, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            } else if (this.#status === this.#PENDING) {

                /* 
                    这里使用数组接收的是未得到结果的函数
                */

				/*
					这里push一个未得到结果的函数,在后面的遍历执行时,得到的结果中返回值时Promise时,
					则会继续调用then,得到对应的结果
				*/
                this.#resolveCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let callbackValue = onFulfilled(this.data);

                            this.#isPromise(callbackValue, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });

                this.#rejectCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let callbackValue = onRejected(this.data)
                            this.#isPromise(callbackValue, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });
            }
        });
        return promise;
    }

	// 判断是否是promise
    #isPromise(callValue, res, rej) {
        // 如果是 Promise 对象
        // 判断返回的数据是不是在MyPromise的原型对象上,如果返回的是MyPromise实例,那么
        // 就判断为true
        if (callValue instanceof MyPromise) {
            // 调用上一次then中成功回调返回的型promise的then方法
            callValue.then(res, rej)
        } else {
            // 如果是一个非MyPromise数值,那么就直接调用返回 ---- promise特性
            res(callValue);
        }
    }

测试


let MyPromise = require('./10-手写Promise对象')


// console.log('1---@');

function isRandom() {

    return new MyPromise(

        (resolve, reject) => {

            let num = Math.random();

            // console.log('2---' + num);

            setTimeout(() => {
                num > 0.5 ?
                    resolve('成功')
                    : reject('失败');

                // console.log('4---¥');
            }, 1000)

            // throw new Error('125676543');
        }
    );
}



isRandom().then(

    data => {
        console.log('5---data: ' + data);

        return isRandom();
    },

    err => console.error('5---err:' + err)

).then(
    value => console.log('6---value:' + value),
    error => console.error('6---error:' + error)
).then(err => console.error(err));

// 5---data: 成功
// 6---value:成功

// or
//5---data: 成功
// 6---error:失败

6 catch实现

需要收集之前then中的错误,然后再catch处理,因为then中没有传递错误处理,所以要创建一个空的错误处理函数,当出发错误时,在调用这个函数会返回一个错误标识,然后拿着标识,和错误数据进行校验,校验符合后触发当前then返回的新promise的reject,然后使用catch调用新的then,将错误输出。

module.exports = class MyPromise {
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    // 保存尚未得到fulfilled状态的then中的函数
    #resolveCallback = [];
    // 保存尚未得到rejected状态的then中的函数
    #rejectCallback = [];

    // Promise初始为待定状态
    #status = this.#PENDING;

    // 保存数据结果
    data = null;

   ···

    then(onFulfilled, onRejected) {
        let promise = new MyPromise((resolve, reject) => {

            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { };

			// 当未传递错误处理函数时会生成一个错误处理函数,这个函数返回一个标识
            onRejected = typeof onRejected === 'function' ? onRejected : () => { return 'reject' };

        
            if (this.#status == this.#FULFILLED) {
                setTimeout(() => {
                    try {
                        // 执行then的成功回调
                        let callbackValue = onFulfilled(this.data);

                        // 判断返回的是否是promise --- 传递 data值, 返回值, 新promise的参数函数
                        this.#isPromise(this.data, callbackValue, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                })
            } else if (this.#status === this.#REJECTED) {
                setTimeout(() => {
                    try {
                        // 执行then的失败回调
                        let callbackValue = onRejected(this.data);

                        // 判断返回的是否是promise
                        this.#isPromise(this.data, callbackValue, resolve, reject);

						/*
							注意,当链式调用且都为传递then的错误回调时,这里返回的callbaclValue是标识

							将其带入校验中进行处理
						*/
                    } catch (error) {
                        reject(error);
                    }
                });
            } else if (this.#status === this.#PENDING) {

                /* 
                    这里使用数组接收的是未得到结果的函数
                */

                this.#resolveCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let callbackValue = onFulfilled(this.data);

                            this.#isPromise(this.data, callbackValue, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });

                this.#rejectCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let callbackValue = onRejected(this.data)
                            this.#isPromise(this.data, callbackValue, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });
            }
        });
        return promise;
    }

 	#isPromise(value, callValue, res, rej) {
	        // 如果是 Promise 对象
	        if (callValue instanceof MyPromise) {
	            // 调用then方法
	            callValue.then(res, rej)
	        } else if (callValue === 'reject') {
	        	// 当校验标识通过以后就可以将错误对象传递到新的promise上,并触发新的promisethen回调
	            rej(value);
	        } else {
	            // 如果是一个非MyPromise数值,那么就直接调用返回
	            res(callValue);
	        }
   	 }

	/* 
		当多个then未传递错误处理函数时,都会创建一个空函数,这个函数返回一标识,用于判断是否
		使用catch后手动触发then中的执行错误回调,接收前一个来自reject的错误数据
	*/
	
    catch(onRejected) {
        return this.then(undefined, onRejected);
    }
}

测试


let MyPromise = require('./10-手写Promise对象')


// console.log('1---@');

function isRandom(resolveStr, rejectStr) {

    return new MyPromise(

        (resolve, reject) => {

            let num = Math.random();

            // console.log('2---' + num);

            setTimeout(() => {
                num > 0.5 ?
                    resolve(resolveStr)
                    : reject(rejectStr);

                // console.log('4---¥');
            }, 1000)

            // throw new Error('125676543');
        }
    );
}



isRandom('成功', '失败').then(

    data => {
        console.log('5---data: ' + data);

        return isRandom('响应', '拒绝');
    },

    // err => console.error('5---err:' + err)

).then(
    value => { console.log('6---value:' + value) },
    // error => console.error('6---error:' + error)
).catch(err => console.log('err' + err))

// ---------------------------------------------
//  err失败

//  5---data: 成功
// err拒绝

// 5---data: 成功
// 6---value:响应

7 resolve, reject 静态方法的实现

   // 添加静态resolve方法
    static resolve(value) {
        // 如果参数是MyPromise实例,直接返回这个实例
        if (value instanceof MyPromise) return value
        // 不是则直接返回一个新的promise 并触发成功
        return new MyPromise(resolve => resolve(value))
    }
    // 添加静态reject方法
    static reject(value) {
    	// 返回一个新的promise,触发拒绝
        return new MyPromise((resolve, reject) => reject(value))
    }

测试

// 测试
MyPromise.resolve(12345).then(data => console.log(data))
// 12345
console.log(MyPromise.resolve(new MyPromise((res, rej) => { Math.random > 0.5 ? res('成功') : rej('失败') })));
// MyPromise { data: null }

MyPromise.reject('error').then(data => console.log(data), err => console.log(err))
// 12345
// error

8 all 实现

all方法时静态的,传入一个promise的数组,当执行的所有promise为成功时,返回成功数据的数组,不成功时,返回第一个错误结果并终止执行

static all(PromiseList) {

        // 用于接收期约结果
        let dataArr = [];

        // 返回promise,用于返回最后的成功、失败的结果
        return new MyPromise((res, rej) => {

            // 遍历传入的promise数组, 拿到对应的promise
            for (const p of PromiseList.entries()) {

                // 调用静态resolve(),分别处理数组中的proimse
                MyPromise.resolve(p[1]).then(
                    data => {
                        // 成功拿到结果则叫入数组
                        dataArr.push(data);

                        // 判断是不是拿到所有的结果,是则返回成功的结果
                        if (dataArr.length === PromiseList.length) {
                            res(dataArr);
                        }
                    },
                    err => {
                        // 数组中一旦出现失败的状态,则立即将这个错误状态返回
                        rej(err)
                    }
                )
            }

        });
    }

测试

MyPromise.all([isRandom('成功1', '失败1'), isRandom('成功2', '失败2')])
    .then(data => console.log(data), err => console.log(err));
//  [ '成功1', '成功2' ]

// or
//  失败1

// or
//  失败2

完整代码

module.exports = class MyPromise {
    // 待定状态 pending
    #PENDING = 'pending';
    // 兑现状态 fulfilled
    #FULFILLED = 'fulfilled';
    // 拒绝状态 rejected
    #REJECTED = 'rejected';

    // 保存尚未得到fulfilled状态的then中的函数
    #resolveCallback = [];
    // 保存尚未得到rejected状态的then中的函数
    #rejectCallback = [];

    // Promise初始为待定状态
    #status = this.#PENDING;

    // 保存数据结果
    data = null;

    constructor(stateFun) {

        // 执行传入的异步函数
        // 使用trycatch捕获
        try {

            /* 
                这里使用bind绑定在promise外部执行的函数this
                避免因为在函数外执行时方法内部this指向改变而无法方法内部变量
                不能使用call方法绑定this指向
                stateFun.call(this.resolve, this.reject);
                因为这里改变的是外部函数被调用时所在作用域的this,如果想要执行不出问题必须使用
                function声明的函数,并且调用resolve与reject时也要使用call来改变指向

                new MyPromise(
                    (resolve, reject) => {
                        let num = Math.random();
                        num > 0.5 ?
                            resolve('成功')
                            : reject('失败');
                    }
                )

            */

            stateFun(this.resolve.bind(this), this.reject.bind(this));

        } catch (error) {
            // 指向错误则调用错误方法
            this.reject(error);
        }
    }

    reject(result) {
        setTimeout(() => {
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;

            // 改变promise状态为失败
            this.#status = this.#REJECTED;

            // 保存失败值
            this.data = result;

            // 在得到结果后将then的参数函数遍历并且执行
            this.#rejectCallback.forEach(callBack => {
                callBack(result);
            });
        });
    }

    resolve(result) {
        setTimeout(() => {
            // 因为状态不可逆所以需要检测状态是不是待定
            if (this.#status !== this.#PENDING) return;
            // 改变promise状态为成功
            this.#status = this.#FULFILLED;
            // 保存成功值
            this.data = result;

            this.#resolveCallback.forEach(callBack => {
                callBack(result);
            });
        });
    }

    then(onFulfilled, onRejected) {
        let promise = new MyPromise((resolve, reject) => {

            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { };

            onRejected = typeof onRejected === 'function' ? onRejected : () => { return 'reject' };

            /* 
                当外部调用then方法时,会接收两个参数(函数),分别用于处理成功的数据和拒绝的结果
            检测当前promise的状态值,并进入对应的函数中执行得到结果
        
        
            添加异步是为了实现不阻塞同步代码的执行,指向返回结果时将函数放在异步中执行就可以
            */
            if (this.#status == this.#FULFILLED) {
                setTimeout(() => {
                    try {
                        // 执行then的成功回调
                        let callbackValue = onFulfilled(this.data);

                        // 判断返回的是否是promise
                        this.#isPromise(this.data, callbackValue, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                })
            } else if (this.#status === this.#REJECTED) {
                setTimeout(() => {
                    try {
                        // 执行then的失败回调
                        let callbackValue = onRejected(this.data);

                        // 判断返回的是否是promise
                        this.#isPromise(this.data, callbackValue, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            } else if (this.#status === this.#PENDING) {

                /* 
                    这里使用数组接收的是未得到结果的函数
                */

                this.#resolveCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let callbackValue = onFulfilled(this.data);

                            this.#isPromise(this.data, callbackValue, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });

                this.#rejectCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let callbackValue = onRejected(this.data);

                            this.#isPromise(this.data, callbackValue, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });
            }
        });
        return promise;
    }


    #isPromise(value, callValue, res, rej) {
        // 如果是 Promise 对象
        if (callValue instanceof MyPromise) {
            // 调用then方法
            callValue.then(res, rej)
        } else if (callValue === 'reject') {
            rej(value);
        } else {
            // 如果是一个非MyPromise数值,那么就直接调用返回
            res(callValue);
        }
    }

    catch(onRejected) {
        return this.then(undefined, onRejected);
    }
	
	 static resolve(value) {
        if (value instanceof MyPromise) return value
        return new MyPromise(resolve => resolve(value))
    }

    static reject(value) {
        return new MyPromise((resolve, reject) => reject(value))
    }

	static all(PromiseList) {

        // 用于接收期约结果
        let dataArr = [];

        // 返回promise,用于返回最后的成功、失败的结果
        return new MyPromise((res, rej) => {

            // 遍历传入的promise数组, 拿到对应的promise
            for (const p of PromiseList.entries()) {

                // 调用静态resolve(),分别处理数组中的proimse
                MyPromise.resolve(p[1]).then(
                    data => {
                        // 成功拿到结果则叫入数组
                        dataArr.push(data);

                        // 判断是不是拿到所有的结果,是则返回成功的结果
                        if (dataArr.length === PromiseList.length) {
                            res(dataArr);
                        }
                    },
                    err => {
                        // 数组中一旦出现失败的状态,则立即将这个错误状态返回
                        rej(err)
                    }
                )
            }

        });
    }
}

问题

以上实现还有点小问题,就是我在外部是可以拿到promise中的结果,而原生中是不能拿到的,这是可以使用私有属性解决的,另外还可以定义一个状态展示,来展示道歉实例处于的状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值