PromiseA+规范的底层原理

PromiseA+

根据promise规范 ,使用TypeScript还原一个完整得Promise


1、promise有三种状态pending,fulfilled,reject。状态生成不能更改

2、new promise时就运行,拥有resolve,reject方法

3、promise有then方法,可以接收resolve方法与reject方法中存入的数据

4、then方法可以链式调用(说明then中返回的也是一个promise)

5、then方法中可返回promise(所以需要对返回值进行处理)

6、catch方法实质就是调用then方法传入失败回调

7、promise规范中还有一个deferred延迟函数 (返回一个对象对象中有promise,resolve,reject)

8、实现Promise.all方法(可使用then方法 说明返回一个promise)

废话不多说 直接贴代码(代码中有注释详解,方便食用)

const enum STATUS { // TS中枚举类型
    pending = 'PENDING',
    fulfilled = 'FULFILLED',
    rejected = 'REJECTED'
}

const isObject = (target:unknown):target is object => typeof target === 'object' && target !== null

function resolvePromise(promise2:Promise,x:any,resolve:(x:unknown)=>void,reject:Function) {
    if(x == promise2){ // 如果x和promise2是一个状态 那就返回类型错误
        return reject(new TypeError('出错了'))
    }
    if(isObject(x) || typeof x === 'function') { // x是一个对象或者是一个函数
        let called = false // 保证只返回一个状态
        try{
            let then = x.then // 获取函数或对象的then方法
            if(typeof then == 'function') { // 判断是不是一个promise函数  规范认为有then方法就是promise
                then.call(x,(y: unknown)=>{
                  if(called) return
                  called = true
                  resolvePromise(promise2, y, resolve, reject) // 再次判断是不是promise
                }, (r:unknown) =>{
                  if(called)return
                  called = true
                  reject(r)
                })
            } else { // 不是函数直接返回即可
                resolve(x)
            }
        } catch (e) {
            if (called) return
            called = true
            reject(e) // 走失败逻辑
        }
    }else {
        // 如果不是那就是一个普通值
        resolve(x)
    }
}

class Promise {
    status: STATUS
    value:any
    reason:any
    onResloveCallbacks: Array<Function>
    onRejectCallbacks: Function[]
    static deferred:any
    static all:any

    constructor (executor:(resolve:(value:unknown)=>void,reject:(reason:any)=>void)=>void){
        this.status = STATUS.pending
        this.value = undefined
        this.reason = undefined
        this.onResloveCallbacks = []
        this.onRejectCallbacks = []

        const resolve = (value?:any)=>{
            if(this.status == STATUS.pending){ // 只有pengding状态才能修改状态
                this.status = STATUS.fulfilled
                this.value = value
                // 订阅未完成的成功回调
                this.onResloveCallbacks.forEach(fn=>fn())
            }
        }
        const reject = (reason?: any)=>{
            if (this.status == STATUS.pending){
                this.status = STATUS.rejected
                this.reason = reason
                // 订阅未完成的失败回调
                this.onRejectCallbacks.forEach(fn=>fn())
            }
        }

        try {
            executor(resolve,reject) // 初始化执行函数
        }catch(e){
            reject(e)
        }
    }
    then(onFulfilled:any, onRejected:Function){
        // 判断是不是函数 不是则重置返回一个函数  使不传参数的then也有返回值 .then().then(data=>data)
        onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : (x:unknown) => x
        onRejected = typeof onRejected == 'function' ? onRejected : (err:unknown) => {throw err}
        // 返回一个promise 支持链式调用
        let promise2 = new Promise((resolve,reject)=>{
            if(this.status == STATUS.pending){ // 如果resolve 或者reject是异步的 那么就是pending状态
                // 发布所有的成功或者失败回调
                this.onResloveCallbacks.push(()=>{
                    setTimeout(() => { // 异步的好处在于能够获取到promise2
                        try {
                            let x = onFulfilled(this.value)
                            // 传入promise2 主要是想拿到resolve reject方法
                            // promise2.resolve = resolve
                            // promise2.reject = reject // 或者直接传入方法
                            resolvePromise(promise2,x,resolve,reject) // 返回参数可能是一个promise 对参数进行判断
                        } catch (error) {
                            reject(error) // 有错误直接reject
                        }
                    }, 0);
                })
                this.onRejectCallbacks.push(()=>{ // 将失败的回调也发布
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason) 
                            resolvePromise(promise2,x,resolve,reject)
                        } catch (error) {
                            reject(error)
                        }
                    }, 0);
                })
            }
            if (this.status == STATUS.fulfilled){ // 状态时fulfilled时
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value) // 接收成功处理函数返回值
                        resolvePromise(promise2,x,resolve,reject)
                    } catch (error) { // 只要运行出错就reject
                        reject(error)
                    }
                }, 0);
            }
            if (this.status == STATUS.rejected){
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason) // 执行失败处理函数 接收其返回值
                        resolvePromise(promise2,x,resolve,reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0);
            }
        })
        return promise2
    }
    catch(errFn: Function){ // 只有错误返回的then方法
        this.then(null, errFn)
    }
}

Promise.deferred = function () {
    let df = {} as any
    df.promise = new Promise((resolve, reject) => {
      df.resolve = resolve
      df.reject = reject
    })
    return df
  }
  const isPromise = function(target:any){
    if(isObject(target) || typeof target == 'function'){
      if(typeof target.then == 'function'){
        return true
      }
    }
    return false
  }
  
  Promise.all = function(values:any[]){
    return new Promise((resolve,reject)=>{
      let arr = [] as any[]
      let times:number = 0
      function collectResult(value:any,key:number){
        arr[key] = value
        if (++times == values.length){
          resolve(arr)
        }
      }
      values.forEach((value:any,key:number)=>{
        if(isPromise(value)){
          value.then((y:unknown)=>{
            collectResult(y, key)
          },reject)
        }else {
          collectResult(value,key)
        }
      })
    })
  }

  export default Promise
对于在resolve和reject返回之前就调用了then方法,处理时使用了发布订阅模式(resolve,reject处于异步时就会出现这种情况)。


PS: 如果对promise不够了解 直接看源码会有些吃力,建议先看看promise文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值