当前位置:网站首页>Manually implement simple promise and its basic functions

Manually implement simple promise and its basic functions

2022-04-23 17:16:00 MiMenge

One 、Promise Basic usage of period function

function Ran(){
    
	return new Promise((resolve, reject) => {
    
		setTimeout(() => {
    
			let ranDomNum = Math.random();	
			//  Simulate asynchronous tasks that may succeed or fail 
			ranDomNum > 0.5 ? resolve(' success ') : reject(' Failure ');
		}, 1000);
	})
}

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

//  success 

// or

//  Failure 

Two 、 Manual implementation Promise Basic function

Realize the idea

1 Declaration method

Because in reference Promise When we use new keyword , So we can use constructors or class Class .

  • Code
class MyPromise{
    
	constructor(){
    
	}
}

//  Use commonjs Exposure module 
module.exports = MyPromise;
  • test
const MyPromise = require('./myPromise');

function Text(){
    
	return new MyPromise((resolve, reject) => {
    
		setTimeout(() => {
    
			let ranDomNum = Math.random();	
			//  Simulate asynchronous tasks that may succeed or fail 
			ranDomNum > 0.5 ? resolve(' success ') : reject(' Failure ');
		}, 1000)
	});
}

Text()

2 Simple implementation resolve and reject

  • Set status and add function

because promise There are three states , Therefore, you need to set the corresponding three states (pending, fulfilled, rejected). When calling promise We need to pass in a function and receive two function parameters (resolve, reject), These two functions are called externally

class MyPromise{
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    constructor(stateFun) {
    
            /*  Use here bind Binding in promise Functions executed externally this  Avoid because when executing outside a function ,  Methods the internal this Point to a variable inside a method that cannot be changed   Out of commission call Method binding this Point to  stateFun.call(this.resolve, this.reject);  Because what is changed here is the scope of the external function when it is called this, If you want to perform without problems, you must use  function Declared function , And call resolve And reject Also use call To change the direction  new MyPromise( (resolve, reject) => { let num = Math.random(); num > 0.5 ? resolve(' success ') : reject(' Failure '); } ) */
			// stateFun The function receives two function parameters , Corresponding reception succeeded / Results of failure 
            stateFun(this.resolve.bind(this), this.reject.bind(this));
    }
}
  • add to resolve,reject

When the corresponding period results are obtained , The corresponding success will be called / Failed call
In addition, a corresponding state should be created each time an appointment is made #status, When you get a successful call ,resolve Function means that a successful result has been obtained , At this time, the state should be #status Change to successful (fulfilled), And save the successful results at this time ( Use #data preservation , be used for then Method return ), When you get a failed call ,reject Method is called , It's triggering reject During call #status The status changes to reject , And save the result of the current error , be used for then Method failed callback

class MyPromise {
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    // Promise The initial status is pending 
    #status = this.#PENDING;

    //  Save the data results 
    data = null;

    constructor(stateFun) {
    
            stateFun(this.resolve.bind(this), this.reject.bind(this));
    }
    
    reject(result) {
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;

            //  change promise The status is failure 
            this.#status = this.#REJECTED;

            //  Save failed value 
            this.data = result;
    }

    resolve(result) {
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;
            //  change promise Status is success 
            this.#status = this.#FULFILLED;
            //  Save success value 
            this.data = result;
    }
}

3 Implement a simple then Method

When you get resolve,reject As a result , Called then The method should be based on #status The state of the call corresponds to then Callback , Be careful then When a callback in is not delivered , And instantiating promise It's a case of throwing an error directly .

class MyPromise {
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    //  Save has not been fulfilled State of then The function in 
    #resolveCallback = [];
    //  Save has not been rejected State of then The function in 
    #rejectCallback = [];

    // Promise The initial status is pending 
    #status = this.#PENDING;

    //  Save the data results 
    data = null;

    constructor(stateFun) {
    

        //  Execute the incoming asynchronous function 
        //  Use trycatch Capture 
        //  Realized the native (resolve,reject)=>{} When an error is thrown directly in , It will also return to trigger reject
        try {
    

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

        } catch (error) {
    
            //  Point to the error and call the wrong method 
            this.reject(error);
        }
    }

    reject(result) {
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;

            //  change promise The status is failure 
            this.#status = this.#REJECTED;

            //  Save failed value 
            this.data = result;

            //  After getting the result, we will then The parameter function traverses and executes 
            this.#rejectCallback.forEach(callBack => {
    
                callBack(result);
            });
    }

    resolve(result) {
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;
            //  change promise Status is success 
            this.#status = this.#FULFILLED;
            //  Save success value 
            this.data = result;

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

    then(onFulfilled, onRejected) {
    

        /*  When incoming then When the callback function is null , Create the corresponding empty function ,  Realized the native then A method is not passed , It can also not affect the implementation  */

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

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

        /*  When called externally then When the method is used , Two parameters are received ( function ), Used to process successful data and rejected results respectively   Detect current promise The state of the value , And enter the corresponding function to execute and get the result  */
        if (this.#status == this.#FULFILLED) {
    //  Status is success 
            //  perform then Successful callbacks in 
            onFulfilled(this.data);
        } else if (this.#status === this.#REJECTED) {
    //  The status is reject 
            //  perform then Callback rejected in 
            onRejected(this.data);
        } else if (this.#status === this.#PENDING) {
    //  Status is pending 

            /*  Here, the array is used to receive the function that does not get the result   Why add a gold array ?  Sometimes we come across a situation , When resolve,reject No results were obtained ,  Then in execution then When the method is used , because #status Unchanged (pending), So you can't call the corresponding callback in time  , This leads to nothing . So we need to put these things that have not got results then Put the function in into the array to be executed ,  When resolve,reject After the result is obtained, it is traversed and executed .  This avoids then I can't get the result when I'm ... */

            this.#resolveCallback.push(onFulfilled);

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

4 Add asynchrony

At first glance, there seems to be no problem when executing the above functions , But we can find the problem by adding the execution order

  • Native
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(' success ')
                    : reject(' Failure ');

                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:  success 

Manual implementation

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(' success ')
                    : reject(' Failure ');

                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: Failure 
// ======5======

To understand why this happens, we first need to know the execution order of the native code
1 Do the synchronization first Output ‘= = = = 1 = = = =’
2 Execute function Output ‘ = = = = 3 = = = = ’
3 perform promise Function output inside the function ‘= = = = 4 = = = =’
4 Encountered timer asynchronous task
5 perform then then The method is asynchronous , Hook in asynchronous
6 perform Synchronous output ‘= = = = 2 = = = =’
1s after Execution timer
7 Output in timer ‘= = = = 5 = = = = ’
because resolve, reject It's asynchronous , So you should output 5, Then the trigger then Callback in method
8 Output ‘= = = = 6 = = = = ’

Sum up , Because of the original then,resolve,reject Only asynchronous tasks have correct execution results , So we should add asynchrony to the manually implemented code

class MyPromise {
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    //  Save has not been fulfilled State of then The function in 
    #resolveCallback = [];
    //  Save has not been rejected State of then The function in 
    #rejectCallback = [];

    // Promise The initial status is pending 
    #status = this.#PENDING;

    //  Save the data results 
    data = null;

    constructor(stateFun) {
    

        //  Execute the incoming asynchronous function 
        //  Use trycatch Capture 
        //  Realized the native (resolve,reject)=>{} When an error is thrown directly in , It will also return to trigger reject
        try {
    

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

        } catch (error) {
    
            //  Point to the error and call the wrong method 
            this.reject(error);
        }
    }

    reject(result) {
    
         setTimeout(()=>{
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;

            //  change promise The status is failure 
            this.#status = this.#REJECTED;

            //  Save failed value 
            this.data = result;

            //  After getting the result, we will then The parameter function traverses and executes 
            this.#rejectCallback.forEach(callBack => {
    
                callBack(result);
            });
		})
    }

    resolve(result) {
    
        setTimeout(()=>{
    
          	//  Because the state is irreversible, it is necessary to detect whether the state is pending 
           if (this.#status !== this.#PENDING) return;
           //  change promise Status is success 
           this.#status = this.#FULFILLED;
           //  Save success value 
           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) {
    //  Status is success 
	        	setTimeout(()=>{
    
	            	//  perform then Successful callbacks in 
	            	onFulfilled(this.data);
	            });
	        } else if (this.#status === this.#REJECTED) {
    //  The status is reject 
	            setTimeout(()=>{
    
 					//  perform then Callback rejected in 
	            	onRejected(this.data);
				})
	        } else if (this.#status === this.#PENDING) {
    //  Status is pending 
	            setTimeout(()=>{
    
					this.#resolveCallback.push(onFulfilled);
	            	this.#rejectCallback.push(onRejected);
				})
	        }
    }
}

//  Be careful  then  It is best to set the asynchrony in the method after the expiration result is obtained 

It's easy to get here promise Function has been realized , The appointment function can be completed .

But there is still an important function ,then Chain call of , It is the core of the periodic function ...


5 then call chaining

Realization ( Omit resolve, reject, constuctor)

then Method needs to return a promise object , Former then After the callback of the method is triggered , We should all receive and judge , Judge then The type of the return value in the callback of the method , If it is not right promise Direct use then Method return promise Of res Go straight back to , If it is promise Then call then Carry on ( Combined with code understanding ), In addition, pay attention to then in pending Processing in state

class MyPromise {
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    //  Save has not been fulfilled State of then The function in 
    #resolveCallback = [];
    //  Save has not been rejected State of then The function in 
    #rejectCallback = [];

    // Promise The initial status is pending 
    #status = this.#PENDING;

    //  Save the data results 
    data = null;

		········
		
    then(onFulfilled, onRejected) {
    
    	/* then Method will return a new promise object , For use then Method to receive the result  */
        let promise = new MyPromise((resolve, reject) => {
    

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

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

            /*  Asynchrony is added so that the execution of synchronous code is not blocked , When pointing to the returned result, the function can be executed asynchronously  */
            if (this.#status == this.#FULFILLED) {
    
                setTimeout(() => {
    
                    try {
    
                        //  perform then Successful callback function , Get the results back 
                        let callbackValue = onFulfilled(this.data);

                        /*  Determine whether the returned is promise, Methods are defined below , there resolve,reject yes   Back to the new promise The success of the / Failed receiving function  */ 
                        this.#isPromise(callbackValue, resolve, reject);
                    } catch (error) {
    
                    	//  If an error occurs, treat it as reject return 
                        reject(error);
                    }
                })
            } else if (this.#status === this.#REJECTED) {
    
                setTimeout(() => {
    
                    try {
    
                        //  perform then The failure callback of  ---  And resolve Empathy 
                        let callbackValue = onRejected(this.data);

                        //  Determine whether the returned is promise
                        this.#isPromise(callbackValue, resolve, reject);
                    } catch (error) {
    
                        reject(error);
                    }
                });
            } else if (this.#status === this.#PENDING) {
    

                /*  Here, the array is used to receive the function that does not get the result  */

				/*  here push A function that does not get a result , When the subsequent traversal is executed , When a value is returned in the obtained result Promise when ,  Will continue to call then, Get the corresponding result  */
                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;
    }

	//  Judge whether it is promise
    #isPromise(callValue, res, rej) {
    
        //  If it is  Promise  object 
        //  Judge whether the returned data is in MyPromise On the prototype object , If you return MyPromise example , that 
        //  Judge as true
        if (callValue instanceof MyPromise) {
    
            //  Call the last then Type returned by successful callback in promise Of then Method 
            callValue.then(res, rej)
        } else {
    
            //  If it is a non MyPromise The number , Then call directly to return  ---- promise characteristic 
            res(callValue);
        }
    }

test


let MyPromise = require('./10- Handwriting Promise object ')


// console.log('[email protected]');

function isRandom() {
    

    return new MyPromise(

        (resolve, reject) => {
    

            let num = Math.random();

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

            setTimeout(() => {
    
                num > 0.5 ?
                    resolve(' success ')
                    : reject(' Failure ');

                // 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:  success 
// 6---value: success 

// or
//5---data:  success 
// 6---error: Failure 

6 catch Realization

Before you need to collect then Mistakes in , And then again catch Handle , because then There is no error handling passed in , So create an empty error handling function , When the departure is wrong , When this function is called, an error ID will be returned , Then take the sign , And error data , Trigger the current alarm after checking that it meets the requirements then Back to the new promise Of reject, And then use catch Call up the new then, Output the error .

module.exports = class MyPromise {
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    //  Save has not been fulfilled State of then The function in 
    #resolveCallback = [];
    //  Save has not been rejected State of then The function in 
    #rejectCallback = [];

    // Promise The initial status is pending 
    #status = this.#PENDING;

    //  Save the data results 
    data = null;

   ···

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

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

			//  When no error handler is passed, an error handler is generated , This function returns an identifier 
            onRejected = typeof onRejected === 'function' ? onRejected : () => {
     return 'reject' };

        
            if (this.#status == this.#FULFILLED) {
    
                setTimeout(() => {
    
                    try {
    
                        //  perform then The successful callback of 
                        let callbackValue = onFulfilled(this.data);

                        //  Determine whether the returned is promise ---  Pass on  data value ,  Return value ,  new promise Parameter function 
                        this.#isPromise(this.data, callbackValue, resolve, reject);
                    } catch (error) {
    
                        reject(error);
                    }
                })
            } else if (this.#status === this.#REJECTED) {
    
                setTimeout(() => {
    
                    try {
    
                        //  perform then The failure callback of 
                        let callbackValue = onRejected(this.data);

                        //  Determine whether the returned is promise
                        this.#isPromise(this.data, callbackValue, resolve, reject);

						/*  Be careful , When called in a chain and all are passed then Error callback for , Back here callbaclValue It's a logo.   Bring it into the verification for processing  */
                    } catch (error) {
    
                        reject(error);
                    }
                });
            } else if (this.#status === this.#PENDING) {
    

                /*  Here, the array is used to receive the function that does not get the result  */

                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) {
    
	        //  If it is  Promise  object 
	        if (callValue instanceof MyPromise) {
    
	            //  call then Method 
	            callValue.then(res, rej)
	        } else if (callValue === 'reject') {
    
	        	//  When the verification ID passes, the error object can be passed to the new promise On , And trigger a new promisethen Callback 
	            rej(value);
	        } else {
    
	            //  If it is a non MyPromise The number , Then call directly to return 
	            res(callValue);
	        }
   	 }

	/*  When more than one then When no error handler is passed , Will create an empty function , This function returns an identifier , Used to determine if   Use catch And then it's triggered manually then Error in callback execution , Receive the previous one from reject Wrong data for  */
	
    catch(onRejected) {
    
        return this.then(undefined, onRejected);
    }
}

test


let MyPromise = require('./10- Handwriting Promise object ')


// console.log('[email protected]');

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(' success ', ' Failure ').then(

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

        return isRandom(' Respond to ', ' Refuse ');
    },

    // 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 Failure 

// 5---data:  success 
// err Refuse 

// 5---data:  success 
// 6---value: Respond to 

7 resolve, reject Implementation of static methods

   //  Add static resolve Method 
    static resolve(value) {
    
        //  If the parameter is MyPromise example , Return to this instance directly 
        if (value instanceof MyPromise) return value
        //  If not, a new promise  And trigger success 
        return new MyPromise(resolve => resolve(value))
    }
    //  Add static reject Method 
    static reject(value) {
    
    	//  Back to a new promise, Trigger reject 
        return new MyPromise((resolve, reject) => reject(value))
    }

test

//  test 
MyPromise.resolve(12345).then(data => console.log(data))
// 12345
console.log(MyPromise.resolve(new MyPromise((res, rej) => {
     Math.random > 0.5 ? res(' success ') : rej(' Failure ') })));
// MyPromise { data: null }

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

8 all Realization

all Method is static , Pass in a promise Array of , When performing all promise When successful , Returns an array of successful data , When it doesn't work , Returns the first error result and terminates execution

static all(PromiseList) {
    

        //  Used to receive the results of the period 
        let dataArr = [];

        //  return promise, Used to return the final success 、 Results of failure 
        return new MyPromise((res, rej) => {
    

            //  Traverse the incoming promise Array ,  Get the corresponding promise
            for (const p of PromiseList.entries()) {
    

                //  Call static resolve(), Handle the... In the array separately proimse
                MyPromise.resolve(p[1]).then(
                    data => {
    
                        //  If the result is obtained successfully, it is called into the array 
                        dataArr.push(data);

                        //  Judge whether you get all the results , If yes, a successful result will be returned 
                        if (dataArr.length === PromiseList.length) {
    
                            res(dataArr);
                        }
                    },
                    err => {
    
                        //  Once a failed state appears in the array , This error status is immediately returned to 
                        rej(err)
                    }
                )
            }

        });
    }

test

MyPromise.all([isRandom(' success 1', ' Failure 1'), isRandom(' success 2', ' Failure 2')])
    .then(data => console.log(data), err => console.log(err));
// [ ' success 1', ' success 2' ]

// or
//  Failure 1

// or
//  Failure 2

Complete code

module.exports = class MyPromise {
    
    //  Pending status  pending
    #PENDING = 'pending';
    //  Cash status  fulfilled
    #FULFILLED = 'fulfilled';
    //  Rejection status  rejected
    #REJECTED = 'rejected';

    //  Save has not been fulfilled State of then The function in 
    #resolveCallback = [];
    //  Save has not been rejected State of then The function in 
    #rejectCallback = [];

    // Promise The initial status is pending 
    #status = this.#PENDING;

    //  Save the data results 
    data = null;

    constructor(stateFun) {
    

        //  Execute the incoming asynchronous function 
        //  Use trycatch Capture 
        try {
    

            /*  Use here bind Binding in promise Functions executed externally this  Avoid because when executing outside a function, the method is internal this Point to a variable inside a method that cannot be changed   Out of commission call Method binding this Point to  stateFun.call(this.resolve, this.reject);  Because what is changed here is the scope of the external function when it is called this, If you want to perform without problems, you must use  function Declared function , And call resolve And reject Also use call To change the direction  new MyPromise( (resolve, reject) => { let num = Math.random(); num > 0.5 ? resolve(' success ') : reject(' Failure '); } ) */

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

        } catch (error) {
    
            //  Point to the error and call the wrong method 
            this.reject(error);
        }
    }

    reject(result) {
    
        setTimeout(() => {
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;

            //  change promise The status is failure 
            this.#status = this.#REJECTED;

            //  Save failed value 
            this.data = result;

            //  After getting the result, we will then The parameter function traverses and executes 
            this.#rejectCallback.forEach(callBack => {
    
                callBack(result);
            });
        });
    }

    resolve(result) {
    
        setTimeout(() => {
    
            //  Because the state is irreversible, it is necessary to detect whether the state is pending 
            if (this.#status !== this.#PENDING) return;
            //  change promise Status is success 
            this.#status = this.#FULFILLED;
            //  Save success value 
            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' };

            /*  When called externally then When the method is used , Two parameters are received ( function ), Used to process successful data and rejected results respectively   Detect current promise The state of the value , And enter the corresponding function to execute and get the result   Asynchrony is added so that the execution of synchronous code is not blocked , When pointing to the returned result, the function can be executed asynchronously  */
            if (this.#status == this.#FULFILLED) {
    
                setTimeout(() => {
    
                    try {
    
                        //  perform then The successful callback of 
                        let callbackValue = onFulfilled(this.data);

                        //  Determine whether the returned is promise
                        this.#isPromise(this.data, callbackValue, resolve, reject);
                    } catch (error) {
    
                        reject(error);
                    }
                })
            } else if (this.#status === this.#REJECTED) {
    
                setTimeout(() => {
    
                    try {
    
                        //  perform then The failure callback of 
                        let callbackValue = onRejected(this.data);

                        //  Determine whether the returned is promise
                        this.#isPromise(this.data, callbackValue, resolve, reject);
                    } catch (error) {
    
                        reject(error);
                    }
                });
            } else if (this.#status === this.#PENDING) {
    

                /*  Here, the array is used to receive the function that does not get the result  */

                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) {
    
        //  If it is  Promise  object 
        if (callValue instanceof MyPromise) {
    
            //  call then Method 
            callValue.then(res, rej)
        } else if (callValue === 'reject') {
    
            rej(value);
        } else {
    
            //  If it is a non MyPromise The number , Then call directly to return 
            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) {
    

        //  Used to receive the results of the period 
        let dataArr = [];

        //  return promise, Used to return the final success 、 Results of failure 
        return new MyPromise((res, rej) => {
    

            //  Traverse the incoming promise Array ,  Get the corresponding promise
            for (const p of PromiseList.entries()) {
    

                //  Call static resolve(), Handle the... In the array separately proimse
                MyPromise.resolve(p[1]).then(
                    data => {
    
                        //  If the result is obtained successfully, it is called into the array 
                        dataArr.push(data);

                        //  Judge whether you get all the results , If yes, a successful result will be returned 
                        if (dataArr.length === PromiseList.length) {
    
                            res(dataArr);
                        }
                    },
                    err => {
    
                        //  Once a failed state appears in the array , This error status is immediately returned to 
                        rej(err)
                    }
                )
            }

        });
    }
}

problem

There are still some small problems in the above implementation , I can get it from the outside promise Results in , And you can't get it in the original , This can be solved using private properties , In addition, you can define a state display , To show the state of the apology instance .

版权声明
本文为[MiMenge]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230553027023.html