实现一个简易版的Promise

promise实现:

首先创建一个 MyPromise

 class MyPromise {
   constructor(executor) {
     this.state = 'pending' // 状态
     this.value = undefined // 保存 resolve 的值
     this.error = undefined // 保存 reject 的值

     // resolve 函数
     const resolve = value => {
       if (this.state === 'pending') {
         this.state = 'fullFilled'
         this.value = value
       }
     }

      // reject 函数
      const reject = error => {
        if (this.state === 'pending') {
          this.state = 'rejected'
          this.error = error
        }
      }

      // 执行通过 new MyPromise() 传进来函数
      executor(resolve, reject)
    }

    // then 方法
    then(onFullFilled, onRejected) {
      // 如果状态为 fullFilled,执行 resolve 回调
      if (this.state === 'fullFilled') {
        onFullFilled(this.value)
      }
      // 如果状态为 fullFilled,执行 reject 回调
      if (this.state === 'rejected') {
         onRejected(this.error)
      }
    }
  }
  // 测试基础功能
  new MyPromise((resolve, reject) => {
    if (Math.random() < 0.5) {
      resolve('fullFilled')
    } else {
      reject('rejected')
    }
  }).then(value => {
    console.log(value)
  }, error => {
    console.log(error)
  })
复制代码

​ 以上代码,姑且实现最简单的 resolvereject,但是在Promise中,如果有语法错误,是会被捕获,然后触发reject的,所以还需要加上错误捕获

实现错误捕获

 try {
   // 执行通过 new MyPromise() 传进来函数
   executor(resolve, reject)
 } catch (e) {
   reject(e)
 }

// 测试捕获功能
new MyPromise((resolve, reject) => {
  // 故意打印一个未定义的值
  console.log(a)
}).then(value => {
  console.log(value)
}, error => {
  // 将会触发失败的回调函数
  console.log(error)
})
复制代码

​ 这样就可以捕获错误并触发reject了,但是如果Promise使用异步触发resolve/reject时,以上代码就无法正常触发then中成功和失败的回调,所以需要利用发布订阅机制,事先保存好成功和失败的回调,然后在resolve/reject触发的时候,再去触发回调

实现异步触发 resolve/reject

...
this.onResolvedCallback = [] // 保存 resolve 回调
this.onRejectedCallback = [] // 保存 reject 回调
 
// resolve 函数
const resolve = value => {
  if (this.state === 'pending') {
    this.state = 'fullFilled'
    this.value = value
    this.onResolvedCallback.forEach(fn => fn())
  }
}

// reject 函数
const reject = error => {
  if (this.state === 'pending') {
     this.state = 'rejected'
     this.error = error
     this.onRejectedCallback.forEach(fn => fn())
  }
}
 // then 方法
 then(onFullFilled, onRejected) {
   ...
   // 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
   if (this.state === 'pending') {
     this.onResolvedCallback.push(() => {
       onFullFilled(this.value)
     })
     
     this.onRejectedCallback.push(() => {
       onRejected(this.error)
     })
   }
 }

// 测试异步代码
new MyPromise((resolve, reject) => {
  setTimeout(() => {
    if (Math.random() < 0.5) {
      resolve(10)
    } else {
      reject(-10)
    }
  }, 1000)
}).then(value => {
  console.log(value)
}, error => {
  console.log(error)
})
复制代码

​ 这样在异步触发resolve/reject的情况下,then中的成功回调和失败回调也能成功触发,接下来,要实现then的链式调用

实现 then 的链式调用

// then 方法
then(onFullFilled, onRejected) {
  let x

  return new MyPromise((resolve, reject) => {
    // 如果状态为 fullFilled,执行 resolve 回调
    if (this.state === 'fullFilled') {
      x = onFullFilled(this.value)
      resolve(x)
    }
    // 如果状态为 fullFilled,执行 reject 回调
    if (this.state === 'rejected') {
      x = onRejected(this.error)
      resolve(x)
    }
    // 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
    if (this.state === 'pending') {
      this.onResolvedCallback.push(() => {
        x = onFullFilled(this.value)
        resolve(x)
      })
      this.onRejectedCallback.push(() => {
        x = onRejected(this.error)
        resolve(x)
      })
    }
  })
}

  // 测试链式调用
  const myPromise = new MyPromise((resolve, reject) => {
    if (Math.random() < 0.5) {
      resolve(10)
    } else {
      reject(-10)
    }
  })
  myPromise.then(value => {
    console.log('sucess:', value)
    return value + 2
  }, error => {
    console.log('fail:', error)
    return error - 2
  }).then(value => {
    console.log('sucess:', value)
    return value + 8
  }, error => {
    console.log('fail:', error)
    return error - 8
  }).then(value => {
    console.log('sucess:', value)
    return value + 10
  }, error => {
    console.log('fail:', error)
    return error - 10
  })
复制代码

​ 这样就实现了then的链式调用,并且保证每个then中成功和失败的回调都返回一个promise对象,然后也要加上错误捕获机制

then 链式操作添加错误捕获

// then 方法
then(onFullFilled, onRejected) {
  let x

  return new MyPromise((resolve, reject) => {
    // 如果状态为 fullFilled,执行 resolve 回调
    if (this.state === 'fullFilled') {
      // 添加错误捕获机制
      try {
        x = onFullFilled(this.value)
        resolve(x)
      } catch (e) {
        reject(e)
      }
    }
    // 如果状态为 fullFilled,执行 reject 回调
    if (this.state === 'rejected') {
      // 添加错误捕获机制
      try {
        x = onRejected(this.error)
        resolve(x)
      } catch (e) {
        reject(e)
      }
    }
    // 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
    if (this.state === 'pending') {
      this.onResolvedCallback.push(() => {
        // 添加错误捕获机制
        try {
          x = onFullFilled(this.value)
          resolve(x)
        } catch (e) {
          reject(e)
        }
      })
      this.onRejectedCallback.push(() => {
        // 添加错误捕获机制
        try {
          x = onRejected(this.error)
          resolve(x)
        } catch (e) {
          reject(e)
        }
      })
    }
  })
}

  // 测试链式调用中错误捕获功能
  const myPromise = new MyPromise((resolve, reject) => {
    if (Math.random() < 0.5) {
      resolve(10)
    } else {
      reject(-10)
    }
  })
  myPromise.then(value => {
    // 故意打印一个未定义的值
    console.log(a)
    return value + 2
  }, error => {
    // 故意打印一个未定义的值
    console.log(a)
    return error - 2
  }).then(value => {
    console.log('sucess:', value)
  }, error => {
    // 将会触发失败的回调函数
    console.log('fail:', error)
  })
复制代码

完整代码如下

 class MyPromise {
    constructor(executor) {
      this.state = 'pending' // 状态
      this.value = undefined // 保存 resolve 的值
      this.error = undefined // 保存 reject 的值
      this.onResolvedCallback = [] // 保存 resolve 回调
      this.onRejectedCallback = [] // 保存 reject 回调

      // resolve 函数
      const resolve = value => {
        if (this.state === 'pending') {
          this.state = 'fullFilled'
          this.value = value
          this.onResolvedCallback.forEach(fn => fn())
        }
      }

      // reject 函数
      const reject = error => {
        if (this.state === 'pending') {
          this.state = 'rejected'
          this.error = error
          this.onRejectedCallback.forEach(fn => fn())
        }
      }

      try {
        // 执行通过 new MyPromise() 传进来函数
        executor(resolve, reject)
      } catch (e) {
        reject(e)
      }
    }

    // then 方法
    then(onFullFilled, onRejected) {
      let x

      return new MyPromise((resolve, reject) => {
        // 如果状态为 fullFilled,执行 resolve 回调
        if (this.state === 'fullFilled') {
          // 添加错误捕获机制
          try {
            x = onFullFilled(this.value)
            resolve(x)
          } catch (e) {
            reject(e)
          }
        }
        // 如果状态为 fullFilled,执行 reject 回调
        if (this.state === 'rejected') {
          // 添加错误捕获机制
          try {
            x = onRejected(this.error)
            resolve(x)
          } catch (e) {
            reject(e)
          }
        }
        // 如果状态为 pending,说明 resolve 或 reject 当前为异步执行,需保存其回调,延后执行
        if (this.state === 'pending') {
          this.onResolvedCallback.push(() => {
            // 添加错误捕获机制
            try {
              x = onFullFilled(this.value)
              resolve(x)
            } catch (e) {
              reject(e)
            }
          })
          this.onRejectedCallback.push(() => {
            // 添加错误捕获机制
            try {
              x = onRejected(this.error)
              resolve(x)
            } catch (e) {
              reject(e)
            }
          })
        }
      })
    }
  }
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享