Handwritten Promise of PromiseA+ specification

foreword

1. What is the meaning of Promise?

In the javascript world, all code is executed in a single thread. Due to this "defect", all network operations and browser events in JavaScript must be executed asynchronously. Ajax can solve this problem, but it is not easy to reuse. JQuery's chained calls can also be solved, and each call will return a JQuery object. In order to better handle Promise appeared, and ECMAScript standardized it.

2. What is the PromiseA+ specification?

In fact,  Promise there are many specifications, such as  Promise/A, Promise/B, Promise/D and  Promise/A upgraded versions of  Promise/A+. The specification was adopted in  ES6 (also known as ES2015)Promise/A+  .

Table of contents

1. Terminology

2. Promise Status (three states and their relationship)

   1. pending 

   2. fulfilled 

   3. rejected

   Summarize:

3. Promise then method and its return value

Four, specification

  1. Specification of parameters

  2. onFulfilled attribute

  3. onRejected attribute

  4. onFulfilled and onRejected should be executed in the microtask stage

  5. The then method can be called multiple times

  6. Return value

  7. resolvePromise

Five, the specific steps to realize the promise (about nine steps);

  1. promise should be a constructor or class        

  2. Define three states  

  3. Initialization state

  4. Implement resolve and reject

  5. For the input parameter processing when instantiating promise

  6. Implement the then method

   7. The return value of then 

  8. The specific implementation of the resolvePromise method

  9. onFulfilled and onRejected are executed in microtasks

So far our simple promise has been realized, we can simply test it


1. Terminology

1. promise is an object or function with a then method;

2. thenable is an object or function with a then method;

3. The value when the value promise status is successful, resolve(value), can be any data type (String Number Boolean undefined thenable promise);

4. The value when the reason promise state fails, reject(reason);

2. Promise Status (three states and their relationship)

   1. pending 

        1.1 Initial state, can be changed.

        1.2 It is in this state before resolve and reject.

        1.3 Pass resolve --> fulfilled state.

        1.4 Pass reject --> rejected status.

   2. fulfilled 

        2.1 The final state cannot be changed.

        2.2 A promise is changed to this state by resolve.

        2.3 A value value must be passed, the value after success.

   3. rejected

        3.1 Final state, unchangeable;

        3.2 A promise is changed to this state by reject;

        3.3 There must be a reason, which is the reason for the failure;

   Summarize:

         pending --> resolve(value)  -->  fulfilled 

         pending --> reject(reason)  --> rejected 

3. Promise then method and its return value

Promise should (promiseA+ specification, the specification is proposed, so it should be used) provide a then method to access the final result, no matter value or reason.

promise.then(onFuilled,onRejected)

Four, specification

  1. Specification of parameters

        1.1 onFulfilled must be a function type, if it is not a function type, it should be ignored (here, ignoring refers to giving a default value, not really ignoring);

        1.2 onRejected must be a function type, if it is not a function type, it should be ignored (same as above);

  2. onFulfilled attribute

        2.1 When the promise becomes fulfilled, onFulfilled should be called, and the parameter is value; (when is onFulfilled executed?)

        2.2 Before the promise becomes fulfilled, onFulfilled should not be called;

        2.3 It can only be called once, and several callback functions can be registered (promise.then().then().then()....);(How to achieve only one call?)

  3. onRejected attribute

        3.1 When the promise becomes rejected, call onRejected, the parameter is reason;

        3.2 onRejected should not be called until the promise becomes rejected.

        3.3 Can only be called once

  4. onFulfilled and onRejected should be executed in the microtask stage

        Why are microtask phases executed?

        You must wait for the previous task to be executed before calling. The microtask is executed after a round of macrotasks is executed;

  5. The then method can be called multiple times

        5.1 After the promise becomes fulfilled, all onFulfilled callbacks should be executed in the order of registration, which can also be understood as executing in the order of .then();

        example:

promise.then(onFulfilled , onRejected).then(onFulfilled1 => ( )).then(....)

        5.2 After the promise becomes rejected, all onRejected callbacks should be executed in the order of registration, which can also be understood as executing in the order of .then();

  6. Return value

        The specification defines then should return a promise 

const promise2 = promise( onFulfilled , onRejected );

        6.1 The execution result of onFulfilled or onRejected is x (anything: value or promise), call resolvePromise;

        6.2 An exception is thrown during the execution of onFulfilled or onRejected, and promise2 needs to be rejected; 

        6.3 If onFulfilled is not a function, promise2 should trigger fulfilled with the value of promise1;

        6.4. If onRejected is not a function, promise2 should be fulfilled with promise1's reason

  7. resolvePromise

        promise2: the return value of the current first promise;

        X: Whether it is the execution result of onFulfilled or onRejected

        resolve, reject: change method        

resolvePromise(promise2, x, resolve, reject)

        7.1 If promise2 and x are equal reject typeError;

        7.2 If x is a promise 

                If x is pending, the promise must remain pending until the state of x changes.

                If x is fulfilled, value --> fulfilled

                If x is rejected, reason --> rejected

        7.3 If x is an Object or Function 

                To get x.then(), if an error is reported, reject reason 

                If then is a function, then.call(x, resolvePromiseFn, rejectPromiseFn)

                Why use call to change this pointer, or when then may cause the pointer to change, so use call to continue to execute the previous logic

Five, the specific steps to realize the promise (about nine steps);

  1. promise should be a constructor or class        

const promise = new promise();

Create a new promise-class.js, today we use class to implement promise

class MPromise{
    constructor(){
    
    }
}

  2. Define three states  

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    constructor(){
    
    }
}

  3. Initialization state

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    constructor(){
        this.status = PENDING;
        this.value = null;
        this.reason = null;
    }
}

  4. Implement resolve and reject

        4.1 These two methods need to change the status from pending to fulfilled / rejected

        4.2 The input parameters are value and reason

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    constructor(){
        this.status = PENDING;
        this.value = null;
        this.reason = null;
    }

    resolve(value){
        // 最终态不可被改变,所以需要加一个判断
        // 只有当 status 为初始态的时候才可以改变
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
        }
        
    }

    reject(reason){
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason= reason;
        }
        
    }
}

  5. For the input parameter processing when instantiating promise

        5.1 The input parameter is a function  

const promise = new promise((resolve,reject)=>{
    
})

        5.2 Accept two parameters, resolve and rejected

        5.3 Initialize the promise to execute this function synchronously , and any error should be thrown through reject

const promise = new promise((resolve,reject)=>{
    axios.get('www.baidu.com')
}).then(result=>{
    // 这里需要注意一下,创建之处就已经执行了
    // 并不是调用 .then()  的时候才会执行
    // 同步执行的,所以可以缓存一个 promise ,需要用到的时候直接取值即可
    // 获取的时候 并不会再次发送请求,所以不用担心流量的偷跑 与 性能的问题
   })
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    constructor(fn){
        this.status = PENDING;
        this.value = null;
        this.reason = null;

        //需要里面调用,有报错需要立马抛出
        try{
            // 考虑严谨性,更改 this 指向为当前环境
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch(e){
            this.reject(e)
        }
    }

    resolve(value){
        // 最终态不可被改变,所以需要加一个判断
        // 只有当 status 为初始态的时候才可以改变
        if(this.status === PENDING){
            this.status = FULFILLED;
            this.value = value;
        }
        
    }

    reject(reason){
        if(this.status === PENDING){
            this.status = REJECTED;
            this.reason= reason;
        }
        
    }
}

  6. Implement the then method

        6.1 then accepts two parameters onFulfilled and onRejected 

        6.2 Check and process parameters, ignore if the parameter is not a function

        6.3 Different functions need to be called according to the state of the current promise

                If promise is fulfilled we need to call onFulfilled

                If the promise is rejected we need to call onRejected

        6.4 First get all the callbacks, because when the status changes, we need to execute the corresponding callbacks whether it is success or failure; create two new arrays to store the success and failure callbacks respectively, when calling then, if it is still pending The state is stored in the array.

        6.5 When the status changes, execute the corresponding callback. Here, the getter setter of es6 is used to monitor the change of status, and perform the corresponding operation when there is a change;

Let me tell you here that if ES5 does not have a getter setter, then we can directly change the status of the status in the resolve and reject methods; use the getter setter to maintain better later, without paying attention to the status;

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    //直接生命两个数组即可,这里的数组不会被修改 只会被push进来
    // 状态完成的 list
    FULFILLED_CALLBACK_LIST = [];
    // 状态失败的 list
    REJECTED_CALLBACK_LIST = [];
    // 存储初始化 status 
    _status = PENDING;
    
    constructor(fn){
        this.status = PENDING;
        this.value = null;
        this.reason = null;

        //需要里面调用,有报错需要立马抛出
        try{
            // 考虑严谨性,更改 this 指向为当前环境
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch(e){
            this.reject(e)
        }
    }


    get status(){
        // 所有真实的 status 
        return this._status;
    }

    set status(newStatus){
        this._status = newStatus;

        // 判断不同的状态 执行不同的逻辑
        switch(newStatus){
            case FULFILLED: {
                // then 方法已经判断过是不是function 所以这里不需要判断
                // 在 status 发生变化的时候,执行对应的回调。
                this.FULFILLED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.value)
                });
                break;
            }
            case REJECTED: {
                this.REJECTED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.reason)
                });
                break;
            }
        }
    }


    resolve(value){
        // 最终态不可被改变,所以需要加一个判断
        // 只有当 status 为初始态的时候才可以改变
        if(this.status === PENDING){
            this.value = value;
            this.status = FULFILLED;

        }
        
    }

    reject(reason){
        if(this.status === PENDING){
            this.reason= reason;
            this.status = REJECTED;

        }
        
    }

    then(onFulfilled, onRejected){
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => throw(reason)
        
        switch(this.status){
            case FULFILLED: {
                fulFilledFn(this.value);
                break;
            }
            case REJECTED: {
                rejectedFn(this.reason);
                break;
            }
            case PENDING: {
                this.FULFILLED_CALLBACK_LIST.push(fulFilledFn);
                this.REJECTED_CALLBACK_LIST.push(rejectedFn);
                break;
            }
        }
        
    }

    isFunction(param){
        return typeof param === 'function';
    }
}

   7. The return value of then 

        7.1 If onFulfilled or onRejected throws an exception e, then the new promise must reject e;

        7.2 The return value should be a promise

        7.3 If onFulfilled is not a function, and promise1 is executed successfully (resolve state), promise2 must return the same state and value; (defined in the specification)

        7.4 If onRejected is not a function, and promise1 refuses to execute, promise2 must return the same status and reason;

        7.5 If onFulfilled or onRejected returns a value x, run the resolvePromise method.

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    //直接生命两个数组即可,这里的数组不会被修改 只会被push进来
    // 状态完成的 list
    FULFILLED_CALLBACK_LIST = [];
    // 状态失败的 list
    REJECTED_CALLBACK_LIST = [];
    // 存储初始化 status 
    _status = PENDING;
    
    constructor(fn){
        this.status = PENDING;
        this.value = null;
        this.reason = null;

        //需要里面调用,有报错需要立马抛出
        try{
            // 考虑严谨性,更改 this 指向为当前环境
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch(e){
            this.reject(e)
        }
    }


    get status(){
        // 所有真实的 status 
        return this._status;
    }

    set status(newStatus){
        this._status = newStatus;

        // 判断不同的状态 执行不同的逻辑
        switch(newStatus){
            case FULFILLED: {
                // then 方法已经判断过是不是function 所以这里不需要判断
                // 在 status 发生变化的时候,执行对应的回调。
                this.FULFILLED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.value)
                });
                break;
            }
            case REJECTED: {
                this.REJECTED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.reason)
                });
                break;
            }
        }
    }


    resolve(value){
        // 最终态不可被改变,所以需要加一个判断
        // 只有当 status 为初始态的时候才可以改变
        if(this.status === PENDING){
            this.value = value;
            this.status = FULFILLED;

        }
        
    }

    reject(reason){
        if(this.status === PENDING){
            this.reason= reason;
            this.status = REJECTED;

        }
        
    }

    then(onFulfilled, onRejected){
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => throw(reason)
        
        //如果 onFulfilled 或者 onRejected 抛出一个异常 e ,那么新的 promise 必须 reject e;
        const fulFilledFnWitchCatch = (resolve, reject, newPromise) => {
            try{
                // 不是一个函数 就直接resolve ,因为有返回值了,所以需要判断
                if(!this.isFunction(onFulfilled)){
                    resolve(this.value)
                }else{
                    const x = fulFilledFn(this.value);
                    this.resolvePromise(newPromise, x, resolve, reject);
                }
            }catch(e) {
                reject(e)
            }
        }
    
        
        const rejectedFnWitchCatch = (resolve, reject, newPromise) => {
            try{
                if(!this.isFunction(onRejected)){
                    reject(this.reason);
                }else{
                    const x =  rejectedFn(this.reason);
                    this.resolvePromise(newPromise, x, resolve, reject); 
                }
                   
            }catch(e) {
                reject(e)
            }
        }

        switch(this.status){
            // then 的返回值是一个promise
            case FULFILLED: {
                const newPromise = new MPromise((resolve, reject) => fulFilledFnWitchCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case REJECTED: {
                const newPromise = new MPromise((resolve, reject) => rejectedFnWitchCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case PENDING: {
                const newPromise = new MPromise((resolve, reject) => {
                    this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWitchCatch(resolve, reject, newPromise));
                    this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWitchCatch(resolve, reject, newPromise));         
                });
                return newPromise;
            }
        }
        
    }
    
    // 规范里定义resolvePromise 需要接受一个 newPromise
    // resolvePromise 函数的意义,就是对promise 各种值的处理
    // 让 promise 可以返回一个结果,无论是 resolve 还是 reject
    resolvePromise(newPromise, x, resolve, reject){
        
    }
    
    
    isFunction(param){
        return typeof param === 'function';
    }
}

  8. The specific implementation of the resolvePromise method

        The meaning of the resolvePromise function is to process various values ​​of the promise,  so that the promise can return a result, whether it is resolve or reject

        8.1 If promise2 and x are equal

        8.1 If x is a promise, the promise must be in the pending state until the state of x changes

                如果 x fulfilled ,value --->  fulfilled

                如果 x rejected ,reason ----> rejected

        8.1 If x is an object / Function

                to get const then = x.then, reject reason

                then is a function, then.call(x, resolvePromiseFn, rejectPromiseFn)

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    //直接生命两个数组即可,这里的数组不会被修改 只会被push进来
    // 状态完成的 list
    FULFILLED_CALLBACK_LIST = [];
    // 状态失败的 list
    REJECTED_CALLBACK_LIST = [];
    // 存储初始化 status 
    _status = PENDING;
    
    constructor(fn){
        this.status = PENDING;
        this.value = null;
        this.reason = null;

        //需要里面调用,有报错需要立马抛出
        try{
            // 考虑严谨性,更改 this 指向为当前环境
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch(e){
            this.reject(e)
        }
    }


    get status(){
        // 所有真实的 status 
        return this._status;
    }

    set status(newStatus){
        this._status = newStatus;

        // 判断不同的状态 执行不同的逻辑
        switch(newStatus){
            case FULFILLED: {
                // then 方法已经判断过是不是function 所以这里不需要判断
                // 在 status 发生变化的时候,执行对应的回调。
                this.FULFILLED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.value)
                });
                break;
            }
            case REJECTED: {
                this.REJECTED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.reason)
                });
                break;
            }
        }
    }


    resolve(value){
        // 最终态不可被改变,所以需要加一个判断
        // 只有当 status 为初始态的时候才可以改变
        if(this.status === PENDING){
            this.value = value;
            this.status = FULFILLED;

        }
        
    }

    reject(reason){
        if(this.status === PENDING){
            this.reason= reason;
            this.status = REJECTED;

        }
        
    }

    then(onFulfilled, onRejected){
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => throw(reason)
        
        //如果 onFulfilled 或者 onRejected 抛出一个异常 e ,那么新的 promise 必须 reject e;
        const fulFilledFnWitchCatch = (resolve, reject, newPromise) => {
            try{
                // 不是一个函数 就直接resolve ,因为有返回值了,所以需要判断
                if(!this.isFunction(onFulfilled)){
                    resolve(this.value)
                }else{
                    const x = fulFilledFn(this.value);
                    this.resolvePromise(newPromise, x, resolve, reject);
                }
            }catch(e) {
                reject(e)
            }
        }
    
        
        const rejectedFnWitchCatch = (resolve, reject, newPromise) => {
            try{
                if(!this.isFunction(onRejected)){
                    reject(this.reason);
                }else{
                    const x =  rejectedFn(this.reason);
                    this.resolvePromise(newPromise, x, resolve, reject); 
                }
                   
            }catch(e) {
                reject(e)
            }
        }

        switch(this.status){
            // then 的返回值是一个promise
            case FULFILLED: {
                const newPromise = new MPromise((resolve, reject) => fulFilledFnWitchCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case REJECTED: {
                const newPromise = new MPromise((resolve, reject) => rejectedFnWitchCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case PENDING: {
                const newPromise = new MPromise((resolve, reject) => {
                    this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWitchCatch(resolve, reject, newPromise));
                    this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWitchCatch(resolve, reject, newPromise));         
                });
                return newPromise;
            }
        }
        
    }
    
    // 规范里定义resolvePromise 需要接受一个 newPromise
    // resolvePromise 函数的意义,就是对promise 各种值的处理
    // 让 promise 可以返回一个结果,无论是 resolve 还是 reject
    resolvePromise(newPromise, x, resolve, reject){
        if(newPromise === x){
            // 返回一个错误信息,信息无所谓什么都可以
            // 为什么要 reject 一个错误信息,因为如果 newPromise 和 x 相等会相互调用,形成一个死循环
            return reject(new TypeError('Type Error,Please....'))
        }

        if(x instanceOf MPromise){
        //如果是promise 肯定有then 方法
            
            x.then(y =>{
                this.resolvePromise(newPromise, y, resolve, reject)
            }, reject);        

        } else if(typeof x === 'object' || this.isFunction(x)){
            // typeof null 也是 object,所以需要加判断
            if(x === null){
                return resolve(x)
            }
        
            // 按照规范的语义化写法
            let then = null;
            try{
                then = x.then;
            }catch(error){
                return reject(error);
            }

            if(this.isFunction(then)){
                // 规范中要求 then 方法 只能被调用一次
                // 定义一个 called 变量,标识是否被调用
    
                let called = false;
                try{
                    // 为了不发生异常错误,更换then 的 this 指向 为x
                    then.call(
                        x,
                        (y) =>{
                            if(called){
                                return;
                            }
                            called = true;
                            // 简单的递归,目的就是找到所有的 x 
                            this.resolvePromise(newPromise, y, resolve, reject);
                        },
                        (r) =>{
                            if(called){
                                return;
                            }
                            called = true;
                            reject(r);
                        }

                    )
                }catch(error){
                    if(called){
                        return;
                    }
                    reject(error);
                }
            }else{
                resolve(x);
            }

        } else {
            resolve(x)
        }
    }
    
    
    isFunction(param){
        return typeof param === 'function';
    }
}

  9. onFulfilled and onRejected are executed in microtasks

        How to achieve?

        queueMicrotask(()=>{}); Pass in a function and call it in the microtask

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';


class MPromise{
    //直接生命两个数组即可,这里的数组不会被修改 只会被push进来
    // 状态完成的 list
    FULFILLED_CALLBACK_LIST = [];
    // 状态失败的 list
    REJECTED_CALLBACK_LIST = [];
    // 存储初始化 status 
    _status = PENDING;
    
    constructor(fn){
        this.status = PENDING;
        this.value = null;
        this.reason = null;

        //需要里面调用,有报错需要立马抛出
        try{
            // 考虑严谨性,更改 this 指向为当前环境
            fn(this.resolve.bind(this), this.reject.bind(this));
        } catch(e){
            this.reject(e)
        }
    }


    get status(){
        // 所有真实的 status 
        return this._status;
    }

    set status(newStatus){
        this._status = newStatus;

        // 判断不同的状态 执行不同的逻辑
        switch(newStatus){
            case FULFILLED: {
                // then 方法已经判断过是不是function 所以这里不需要判断
                // 在 status 发生变化的时候,执行对应的回调。
                this.FULFILLED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.value)
                });
                break;
            }
            case REJECTED: {
                this.REJECTED_CALLBACK_LIST.forEach(callback=>{
                     callback(this.reason)
                });
                break;
            }
        }
    }


    resolve(value){
        // 最终态不可被改变,所以需要加一个判断
        // 只有当 status 为初始态的时候才可以改变
        if(this.status === PENDING){
            this.value = value;
            this.status = FULFILLED;

        }
        
    }

    reject(reason){
        if(this.status === PENDING){
            this.reason= reason;
            this.status = REJECTED;

        }
        
    }

    then(onFulfilled, onRejected){
        const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled : (value) => value
        const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason) => throw(reason)
        
        //如果 onFulfilled 或者 onRejected 抛出一个异常 e ,那么新的 promise 必须 reject e;
        const fulFilledFnWitchCatch = (resolve, reject, newPromise) => {
            queueMicrotask(() => {
                try{
                    // 不是一个函数 就直接resolve ,因为有返回值了,所以需要判断
                    if(!this.isFunction(onFulfilled)){
                        resolve(this.value)
                    }else{
                        const x = fulFilledFn(this.value);
                        this.resolvePromise(newPromise, x, resolve, reject);
                    }
                }catch(e) {
                    reject(e)
                }
            });
        }
    
        
        const rejectedFnWitchCatch = (resolve, reject, newPromise) => {
            queueMicrotask(() => {
                try{
                    if(!this.isFunction(onRejected)){
                        reject(this.reason);
                    }else{
                        const x =  rejectedFn(this.reason);
                        this.resolvePromise(newPromise, x, resolve, reject); 
                    }
                }catch(e) {
                    reject(e)
                }
            });
        }

        switch(this.status){
            // then 的返回值是一个promise
            case FULFILLED: {
                const newPromise = new MPromise((resolve, reject) => fulFilledFnWitchCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case REJECTED: {
                const newPromise = new MPromise((resolve, reject) => rejectedFnWitchCatch(resolve, reject, newPromise));
                return newPromise;
            }
            case PENDING: {
                const newPromise = new MPromise((resolve, reject) => {
                    this.FULFILLED_CALLBACK_LIST.push(() => fulFilledFnWitchCatch(resolve, reject, newPromise));
                    this.REJECTED_CALLBACK_LIST.push(() => rejectedFnWitchCatch(resolve, reject, newPromise));         
                });
                return newPromise;
            }
        }
        
    }
    

    catch(onRejected){
        return this.then(null, onRejected)
    }


    // 规范里定义resolvePromise 需要接受一个 newPromise
    // resolvePromise 函数的意义,就是对promise 各种值的处理
    // 让 promise 可以返回一个结果,无论是 resolve 还是 reject
    resolvePromise(newPromise, x, resolve, reject){
        if(newPromise === x){
            // 返回一个错误信息,信息无所谓什么都可以
            // 为什么要 reject 一个错误信息,因为如果 newPromise 和 x 相等会相互调用,形成一个死循环
            return reject(new TypeError('Type Error,Please....'))
        }

        if(x instanceOf MPromise){
        //如果是promise 肯定有then 方法
            
            x.then(y =>{
                this.resolvePromise(newPromise, y, resolve, reject)
            }, reject);        

        } else if(typeof x === 'object' || this.isFunction(x)){
            // typeof null 也是 object,所以需要加判断
            if(x === null){
                return resolve(x)
            }
        
            // 按照规范的语义化写法
            let then = null;
            try{
                then = x.then;
            }catch(error){
                return reject(error);
            }

            if(this.isFunction(then)){
                // 规范中要求 then 方法 只能被调用一次
                // 定义一个 called 变量,标识是否被调用
    
                let called = false;
                try{
                    // 为了不发生异常错误,更换then 的 this 指向 为x
                    then.call(
                        x,
                        (y) =>{
                            if(called){
                                return;
                            }
                            called = true;
                            // 简单的递归,目的就是找到所有的 x 
                            this.resolvePromise(newPromise, y, resolve, reject);
                        },
                        (r) =>{
                            if(called){
                                return;
                            }
                            called = true;
                            reject(r);
                        }

                    )
                }catch(error){
                    if(called){
                        return;
                    }
                    reject(error);
                }
            }else{
                resolve(x);
            }

        } else {
            resolve(x)
        }
    }
    
    
    isFunction(param){
        return typeof param === 'function';
    }
}

So far our simple promise has been realized, we can simply test it

const test = new MPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve(1111);
    },1000)
}).then(console.log)



const test = new MPromise((resolve, reject) => {
    setTimeout(()=>{
        reject(1111);
    },1000)
}).then((value) => {
    console.log('完成' + value)
}).catch((reason) => {
    console.log('报错' + reason)
})

 

 At this point, the instance method resolve reject has been added, and the static method will be added later;

Guess you like

Origin blog.csdn.net/weixin_56650035/article/details/121070438