手写promise

132 阅读1分钟

基础代码

new Promise((resolve, reject)=>{
  resolve(123)
}).then(res=>{}, error=>{})
 class Promise{
   constructor(executor){
   // pending:处理中,fulfilled:成功,rejected: 失败
     this.status = 'pending'
     this.value = undefined
     this.reason = undefined
     let resolve = value=>{
       if(this.status === 'pending'){
         this.status = 'fulfilled'
         this.value = value
       }
     }
     let reject = reason=>{
     if(this.status === 'pending'){
         this.status = 'rejected'
         this.reason = reason
       }
     }
     executor(resolve, reject)
   }
   then(onResolved, onRejected){
     if(this.status === 'fulfilled'){
       onResolved(this.value)
     }
     if(this.status === 'onRejected'){
       onRejected(this.reason)
     }
   }
 }

支持异步

  • 思路
  1. 当then中status=pending时,把resolve和rejectpush进数组中缓存起来,相当于异步队列,当resole或reject函数调用时,遍历数组调用函数
  class Promise{
   constructor(executor){
   // pending:处理中,fulfilled:成功,rejected: 失败
     this.status = 'pending'
     this.value = undefined
     this.reason = undefined
     this.onResolvedCallbacks = []
     this.onRejectedCallbacks = []
     let resolve = value=>{
       if(this.status === 'pending'){
         this.status = 'fulfilled'
         this.value = value
         this.onResolvedCallbacks.forEach(v=>v())
       }
     }
     let reject = reason=>{
     if(this.status === 'pending'){
         this.status = 'rejected'
         this.reason = reason
         this.onRejectedCallbacks.forEach(v=>v())
       }
     }
     try{
       executor(resolve, reject)
     }catch(error){
       reject(error)
     }
     
   }
   then(onResolved, onRejected){
     if(this.status === 'fulfilled'){
       onResolved(this.value)
     }
     if(this.status === 'rejected'){
       onRejected(this.reason)
     }
     if(this.status === 'pending'){
       this.onResolvedCallbacks.push(()=>{onResolved(this.value)})
       this.onRejectedCallbacks.push(()=>{onRejected(this.reason)})
     }
   }
 }
 
 new Promise((resolve, reject)=>{
   setTimeout(()=>{
     resolve(123)
   }, 1000)
 }).then(res=>{
   console.log(res)
 }, error=>{})

支持链式调用 new Promise().then().then()

  • then函数中返回Promise实例
  • 在then的onResolved或onRejected函数返回值作为入参在promise的resolve或reject中
 class Promise {
      constructor(executor) {
        // pending:处理中,fulfilled:成功,rejected: 失败
        this.status = 'pending'
        this.value = undefined
        this.reason = undefined
        this.onResolvedCallbacks = []
        this.onRejectedCallbacks = []
        let resolve = value => {
          if (this.status === 'pending') {
            this.status = 'fulfilled'
            this.value = value
            this.onResolvedCallbacks.forEach(v => v())
          }
        }
        let reject = reason => {
          if (this.status === 'pending') {
            this.status = 'rejected'
            this.reason = reason
            this.onRejectedCallbacks.forEach(v => v())
          }
        }
        try {
          executor(resolve, reject)
        } catch (error) {
          reject(error)
        }

      }
      then(onResolved, onRejected) {
        const promise2 = new Promise((resolve, reject) => {
          if (this.status === 'fulfilled') {
            const x = onResolved(this.value)
            resolve(x)
          }
          if (this.status === 'rejected') {
            const x = onRejected(this.reason)
            reject(x)
          }
          if (this.status === 'pending') {
            this.onResolvedCallbacks.push(() => {
              const x = onResolved(this.value)
              resolve(x)

            })
            this.onRejectedCallbacks.push(() => {
              const x = onRejected(this.reason)
              reject(x)
            })
          }
        })
        return promise2
      }
    }

    new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(123)
      }, 1000)
    }).then(res => {
      return res
    }, error => {
      return error
      // console.log(error)
    }).then(res => {
      console.log(res);
    }, ero => {
      console.log(ero);
    })