编辑代码

/**
 * Promise 基本原理
 * 
 * 1、Promise是一个类,在执行这个类时,会传入一个执行器,这个执行器会立即执行
 * 2、Promise会有三种状态:Pedding 等待 Fullfilled 完成 Rejected 失败
 * 3、状态只能由Pedding --> Fullfilled或者Pedding --> Rejected,且一旦发生改变,便不可发生二次更改
 * 4、Promise中使用resolve和reject两个函数来更新状态
 * 5、then方法内部做的事情就是状态判断,如果状态是成功,调用成功回调函数,如果状态是失败,调用失败回调函数
 * 
 * 实现then方法的链式调用
 * 
 * then方法要链式调用那么就需要返回一个Promise对象
 * then方法里面return一个返回值作为下一个then方法的参数,如果是return一个Promise对象,那么就需要判断它的状态
 * 
 * */

 const PEDDING = 'pedding'
 const FULLFILLED = 'fullfilled'
 const REJECTED = 'rejected'

 const onFullfilledCallbacks = []
 const onRejectedCallbacks = []

 class MyPromise{
    static resolve(parameter){
        if(parameter instanceof MyPromise){
            return parameter
        }
        return new MyPromise(resolve => {
            resolve(parameter)
        })
    }

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

    constructor(exector){
        try{
          exector(this.resolve,this.reject)          
        }catch(error){
          this.reject(error)
        }
    }

    status  = PEDDING

    value = null

    reason = null

    resolve = val => {
        if(this.status === PEDDING){
            this.status = FULLFILLED

            this.value = val

            while(onFullfilledCallbacks.length){
                (onFullfilledCallbacks.shift())(val)
            }
        }
    }

    reject = error => {
        if(this.status === PEDDING){
            this.status = REJECTED

            this.reason = error

            while(onRejectedCallbacks.length){
                (onRejectedCallbacks.shift())(error)
            }
        }
    }

    then = (onFullfilled,onRejected) => {
        onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        const c = new MyPromise((resolve,reject) => {
            const fullfilledMicrotask = () => {
                queueMicrotask(() => {
                    try{
                        const x = onFullfilled(this.value)

                        resolvePromise(promise2,x,resolve,reject)
                    }catch(error){
                        reject(error)
                    }
                })
            }

            const rejectedMicrotask = () => {
                queueMicrotask(() => {
                    try{
                        const x =  onRejected(this.reason)

                        resolvePromise(promise2,x,resolve,reject)
                    }catch(error){
                        reject(error)
                    }
                })
            }

            if(this.status === FULLFILLED){
               fullfilledMicrotask()
            }else if(this.status === REJECTED){
               rejectedMicrotask()
            }else{
                onFullfilledCallbacks.push(fullfilledMicrotask)
                onRejectedCallbacks.push(rejectedMicrotask)
            }
        })

        return promise2
    }
 }

 function resolvePromise(promise2,x,resolve,reject){
    if(promise2 === x){
        return reject(new TypeError('Chaining cycle deteced for promise #<Promise>'))
    }
    if(typeof x === 'function' || typeof x === 'object'){
        if(x === null){
            resolve(x)
        }

        let then

        try{
           then = x.then
        }catch(err){
           return reject(err)
        }

        if(typeof then ==='function'){
            let called = false

            try{
               then.call(
                   x,
                   y => {
                       if(called)return
                       called = true
                       resolvePromise(promise2,y,resolve,reject)
                   },
                   r => {
                       if(called)return
                       called = true
                       reject(r)
                   }
               )
            }catch(error){
               if(called)return

               reject(error)
            }
        }else{
            resolve(x)
        }
    }else{
        resolve(x)
    }
 }

 module.exports = MyPromise