用TypeScript手写Promise原理

118 阅读4分钟

回顾上一篇文章的Promise的实现,Promise的三种状态pending,fulfilled,fail Promise两个参数,resolve,reject Promise实现第一步------- Promise回调实现

  1. actiontype 新建一个actiontype.ts,并且初始化tsconfig.json,package.json
// 返回值可以是void,但是用any? 因为any包含void
type ResolveType = (resolve: any) => any
type RejectType = (reject: any) => any
type Executor = (resolve: ResolveType, reject: RejectType) => any

export { ResolveType, RejectType, Executor }
  1. Promise回调实现 新建promise.ts
import { ResolveType, RejectType, Executor } from './actiontype'

class Promise<T = any> {
  public resolve!: ResolveType
  public reject!: RejectType
  public status!: string // 状态
  public resolve_executor_value!: any
  public reject_executor_value!: any
  constructor(executor: Executor) {
    this.status = "pending" //初始状态
    this.resolve = (success_value: any): any => {
      if(this.status === 'pending') {
        this.status = 'fulfilled'
        this.resolve_executor_value = success_value
        console.log('fulfilled')
      }
    }
    this.reject = (fail_value: any): any => {
      if(this.status === 'pending') {
        this.status = 'fail'
        this.reject_executor_value = fail_value
        console.log('fail')
      }
    }
    executor(this.resolve, this.reject)
  }

  then(resolveInThen: ResolveType, rejectInThen: RejectType) {
    if(this.status === 'fulfilled') {
      resolveInThen(this.resolve_executor_value)
      console.log('resolveInThen')
    }
    if(this.status === 'fail') {
      rejectInThen(this.reject_executor_value)
      console.log('rejectInThen')
    }
  }
}

export default Promise
  1. 测试类实现 新建test.ts 并在package.json中添加 "tsc": "ts-node ./test.ts"
import Promise from './Promise'
let promise = new Promise((resolve, reject) => {
  resolve('成功了')
  reject('失败了')
})

promise.then(resolveData => {
  console.log('resolveData', resolveData)
}, (rejectData) => {
  console.log('rejectData', rejectData)
})

报错的实现,发生异常的处理,可以使用try{}catch {}捕获异常

try {
  executor(this.resolve, this.reject)
} catch (err: any) {
  this.status = 'pending'
  this.reject(err.toString())
  throw new Error("程序终止...")
}

Promise完整版的代码如下:

import { ResolveType, RejectType, Executor } from './actiontype'

class Promise<T = any> {
  public resolve!: ResolveType
  public reject!: RejectType
  public status!: string // 状态
  public resolve_executor_value!: any
  public reject_executor_value!: any
  constructor(executor: Executor) {
    this.status = "pending" //初始状态
    this.resolve = (success_value: any): any => {
      if(this.status === 'pending') {
        this.status = 'fulfilled'
        this.resolve_executor_value = success_value
      }
    }
    this.reject = (fail_value: any): any => {
      if(this.status === 'pending') {
        this.status = 'fail'
        this.reject_executor_value = fail_value
      }
    }
    try {
      executor(this.resolve, this.reject)
    } catch (err: any) {
      this.status = 'pending'
      this.reject(err.toString())
      throw new Error("程序终止...")
    }
  }

  then(resolveInThen: ResolveType, rejectInThen: RejectType) {
    if(this.status === 'fulfilled') {
      resolveInThen(this.resolve_executor_value)
    }
    if(this.status === 'fail') {
      rejectInThen(this.reject_executor_value)
    }
  }
}

export default Promise

同步级联then方法的实现 要实现的效果如下: test.ts

promise.then(resolveData => {
  console.log('resolveData', resolveData)
  return 'ok'
}, (rejectData) => {
  console.log('rejectData', rejectData)
  return 'fail'
}).then((resolveData2) => {
  console.log('resolveData2', resolveData2)
  return 'ok2'
}, (rejectData2) => {
  console.log('rejectData', rejectData2)
  return 'fail2'
}).then((resolveData3) => {
  console.log('resolveData3', resolveData3)
  return 'ok3'
}, (rejectData3) => {
  console.log('rejectData', rejectData3)
  return 'fail3'
})

要想实现同步级联,首先then里面必须传入一个Promise,用一个变量接受resolve函数的值,完整的then代码如下:

 then(resolveInThen: ResolveType, rejectInThen: RejectType) {
      let result
.2    return new Promise((resolve, reject) => {
      console.log('this', this) // 此时的this指的是最外面的p
      if(this.status === 'fulfilled') {
        result = resolveInThen(this.resolve_executor_value)
 .4     resolve(result)
      }
      if(this.status === 'fail') {
        result = rejectInThen(this.reject_executor_value)
        reject(result)
      }
    })
  }

补充解释: 当我们执行上面代码2行的时候,new Promise会再次调用constructor里面executor执行器,并传递resolve和reject到executor,那么此时的this是谁?此时的this指的是最外面的p;4行的resolve怎么解释呢?会再次调用resolve方法,并且把result传递过去,此时的resolve方法是本次new Promise产生的,所以会存储在本次的resolve_executor_value上,依次循环.

Promise第二部---------异步 看看异步的场景

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功')
    reject('失败)
  }, 5)
})

用订阅和发布来实现上述场景

 public resolve_then_callbacks: (() => void)[] = []
 public reject_then_callbacks: (() => void)[] = []
 if(this.status === 'pending') {
   // 订阅
   this.resolve_then_callbacks.push(() => {
     result = resolveInThen(this.resolve_executor_value)
     resolve(result)
   })
   this.reject_then_callbacks.push(() => {
     result = rejectInThen(this.reject_executor_value)
     reject(result)
   })
 }

多个异步怎么操作 第一种实现方式

promise.then(resolveData => {
  console.log('resolveData', resolveData)
  // 怎么实现
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('成功了promise.then')
    }, 5)
  })
}, (rejectData) => {
  console.log('rejectData', rejectData)
  return 'fail'
})

实现方式,怎么判断是promise类型的

function isPromise(val: any): val is Promise {
  return isObject(val) && isFunction(val.then)
}

function isObject(val: any): val is Record<any, any> {
  return val !== null && typeof val === 'object'
}

function isFunction(data: any): data is Function {
  return typeof data === "function"
}

使用setTImeout解决方案

 if(this.status === 'pending') {
    // 订阅
    this.resolve_then_callbacks.push(() => {
      result = resolveInThen(this.resolve_executor_value)
      if(isPromise(result)) { // promise
        // 先执行promise,再setTimeout
        setTimeout(() => {
          resolve(result.resolve_executor_value)
        }, 5)
      } else {
        resolve(result) // 普通的数据
      }
    })
    this.reject_then_callbacks.push(() => {
      result = rejectInThen(this.reject_executor_value)
      reject(result)
    })
}

优化上述代码:

if(this.status === 'pending') {
  // 订阅
  this.processManyAsyncAndSync(resolveInThen, rejectInThen, resolve, reject)
}
processManyAsyncAndSync(resolveInThen: ResolveType, rejectInThen: RejectType, resolve: ResolveType, reject: RejectType) {
    let result: any
    this.resolve_then_callbacks.push(() => {
      result = resolveInThen(this.resolve_executor_value)
      if(isPromise(result)) { // promise
        // 先执行promise,再setTimeout
        setTimeout(() => {
          resolve(result.resolve_executor_value)
        }, 5)
      } else {
        resolve(result) // 普通的数据
      }
    })
    this.reject_then_callbacks.push(() => {
      result = rejectInThen(this.reject_executor_value)
      reject(result)
    })
 }

第二种实现方案

processManyAsyncAndSync(resolveInThen: ResolveType, rejectInThen: RejectType, resolve: ResolveType, reject: RejectType) {
    let result: any
    this.resolve_then_callbacks.push(() => {
      result = resolveInThen(this.resolve_executor_value)
      if(isPromise(result)) { // promise
        // 先执行promise,再setTimeout
        result.then((resolveSuccess) => {
          resolve(resolveSuccess)
        }, (rejectSuccess) => {
          reject(rejectSuccess)
        })
      } else {
        resolve(result) // 普通的数据
      }
    })
    this.reject_then_callbacks.push(() => {
      result = rejectInThen(this.reject_executor_value)
      reject(result)
    })
  }

手写Promise.all实现

 static all(promises: Promise[]): Promise {
    return new Promise((resolve, reject) => {
      let allPromiseResolveValue: Array<any> = []
      promises.forEach((promise, index) => {
        promise.then((resolveSuccess) => {
          ProcessData(resolveSuccess, index)
        }, (rejectFail) => {
          reject(rejectFail) // 只要有一个promise对象的resolve执行失败
          return
        })
      })
      function ProcessData(resolveSuccess: any, index: number) {
        allPromiseResolveValue[index] = resolveSuccess
        if(index === promises.length - 1) { // 所有的promise对象resolve函数全部执行完毕
          resolve(allPromiseResolveValue)
        }
      }
    })
  }

测试案例

const promise1 = new Promise((resolve, reject) => {
  console.log('第一个promise同步区域')
  setTimeout(() => {
    resolve('setTimeout第一个promise')
  }, 5)
})

const promise2 = new Promise((resolve, reject) => {
  console.log('第二个promise同步区域')
  setTimeout(() => {
    resolve('setTimeout第二个promise')
  }, 5)
})

const promise3 = new Promise((resolve, reject) => {
  console.log('第三个promise同步区域')
  setTimeout(() => {
    resolve('setTimeout第三个promise')
  }, 5)
})

Promise.all([promise1, promise2, promise3]).then(resolveValue => {
  console.log(resolveValue)
}, rejectValue => {
  console.log(rejectValue)
})

all只要有一个reject,然后终止并返回reject的promise