前端手写Promise并完美通过promises-aplus-tests 872 项测试


const PENDDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
  constructor(executor) {
    //初始状态
    this.status = PENDDING
    //存放成功的值
    this.value = undefined
    //存放失败的原因
    this.reason = undefined
    //成功存放成功的回调
    this.onResolvedCallbacks = []
    //失败存放失败的回调
    this.onRejectedCallbacks = []
    const resolve = (data) => {
      //状态是pending才能修改状态
      if (this.status === PENDDING) {
        this.status = FULFILLED
        this.value = data
        this.onResolvedCallbacks.forEach((fn) => fn())
      }
    }
    const reject = (reason) => {
      //状态是pending才能修改状态
      if (this.status === PENDDING) {
        this.status = REJECTED
        this.reason = reason
        this.onRejectedCallbacks.forEach((fn) => fn())
      }
    }
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  resolvedPromise(promise, result, resolve, reject) {
    if (promise === result) reject(new TypeError('Chaining cycle detected for promise'))
    // 在 JavaScript 中,函数也是一种对象,因此也可以具有 then 方法。如果 result 是一个函数并且具有 then 方法,那么就会按照 Promise/A+ 规范来处理它,调用它的 then 方法,并根据其返回值来决定当前 Promise 的状态和值。
    if ((result && typeof result === 'object') || typeof result === 'function') {
    //处理嵌套的Promise对象思路是使用递归
    //如果传入的 result 是一个对象或者一个函数的话,令 then = result.then。
    //然后判断 then 是否是一个函数,如果是就说明 result 是一个 promise 对象,那就调用 then,并且    把 result 作为 this,然后在成功回调中继续调用 resolvedPromise 并且把拿到的值作为新的 result 传入,其他不变。
    //如果 then 不是一个函数,那就说明 result 是一个函数或者是一个普通对象,那就直接 resolve。
    //如果传入的 result 不是一个对象且不是一个函数,就直接 resolve 即可,同时这也是该递归的最终状态。
    //为了保证成功和失败只能调用其中一个,声明变量 called 来作为标记。
    //使用 try...catch 来进行异常处理。
      let called
      try {
        let then = result.then
        if (typeof then === 'function') {
          then.call(
            result,
            (value) => {
              if (called) return
              called = true
              this.resolvedPromise(promise, value, resolve, reject)
            },
            (reason) => {
              if (called) return
              called = true
              reject(reason)
            }
          )
        } else {
          if (called) return
          called = true
          resolve(result)
        }
      } catch (error) {
        if (called) return
        called = true
        reject(error)
      }
    } else {
      resolve(result)
    }
  }
  then(onFulfilled, onRejected) {
    //处理then的参数,如果参数不是函数,那么忽略它
    if (typeof onFulfilled !== 'function')
      onFulfilled = (value) => {
        return value
      }
    if (typeof onRejected !== 'function')
      onRejected = (reason) => {
        throw reason
      }
    let promise = new MyPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        //使用settimeout处理then方法的异步执行
        setTimeout(() => {
          try {
            this.resolvedPromise(promise, onFulfilled(this.value), resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            this.resolvedPromise(promise, onRejected(this.reason), resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
      }
      if (this.status === PENDDING) {
        this.onResolvedCallbacks.push(() =>
          setTimeout(() => {
            try {
              this.resolvedPromise(promise, onFulfilled(this.value), resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        )
        this.onRejectedCallbacks.push(() =>
          setTimeout(() => {
            try {
              this.resolvedPromise(promise, onRejected(this.reason), resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        )
      }
    })
    return promise
  }
  catch(err) {
    return this.then(null, err)
  }
  static resolve(value) {
    let promise = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        promise.resolvedPromise(promise, value, resolve, reject)
      })
    })
    return promise
  }
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason)
    })
  }
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let results = []
      let count = 0
      let index = 0
      for (let promise of promises) {
        let resultIndex = index
        index += 1
        MyPromise.resolve(promise).then(
          (e) => {
            count += 1
            results[resultIndex] = e
            if (count === index) resolve(results)
          },
          (reason) => {
            reject(reason)
          }
        )
      }
      if (index === 0) resolve(results)
    })
  }
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        MyPromise.resolve(promise).then(resolve, reject)
      })
    })
  }
}
//以下是用于测试的代码
MyPromise.defer = MyPromise.deferred = function () {
    let dfd = {}
    dfd.promise = new MyPromise((resolve, reject) => {
      dfd.resolve = resolve
      dfd.reject = reject
    })
    return dfd
  }
module.exports = MyPromise

安装测试脚本

npm install -g promises-aplus-tests

然后在 MyPromise 所在文件 (promise.js) 的目录下执行:

promises-aplus-tests promise.js

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的 Promise 实现: ```javascript class MyPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; const resolve = value => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onResolvedCallbacks.forEach(cb => cb()); } }; const reject = reason => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(cb => cb()); } }; try { executor(resolve, reject); } catch (error) { reject(error); } } then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }; const promise2 = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } if (this.state === 'rejected') { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); } if (this.state === 'pending') { this.onResolvedCallbacks.push(() => { setTimeout(() => { try { const x = onFulfilled(this.value); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); this.onRejectedCallbacks.push(() => { setTimeout(() => { try { const x = onRejected(this.reason); this.resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); } }); return promise2; } catch(onRejected) { return this.then(null, onRejected); } resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { return reject(new TypeError('Chaining cycle detected for promise')); } let called = false; if (x instanceof MyPromise) { x.then(value => { this.resolvePromise(promise2, value, resolve, reject); }, reason => { if (called) return; called = true; reject(reason); }); } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { const then = x.then; if (typeof then === 'function') { then.call(x, value => { if (called) return; called = true; this.resolvePromise(promise2, value, resolve, reject); }, reason => { if (called) return; called = true; reject(reason); }); } else { resolve(x); } } catch (error) { if (called) return; called = true; reject(error); } } else { resolve(x); } } static resolve(value) { if (value instanceof MyPromise) { return value; } return new MyPromise(resolve => resolve(value)); } static reject(reason) { return new MyPromise((resolve, reject) => reject(reason)); } static all(promises) { return new MyPromise((resolve, reject) => { const values = []; let count = 0; for (let i = 0; i < promises.length; i++) { MyPromise.resolve(promises[i]).then(value => { values[i] = value; count++; if (count === promises.length) { resolve(values); } }, reason => { reject(reason); }); } }); } static race(promises) { return new MyPromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { MyPromise.resolve(promises[i]).then(value => { resolve(value); }, reason => { reject(reason); }); } }); } } ``` 这个 Promise 实现基本上实现了 Promise/A+ 规范,并支持 then、catch、resolve、reject、all、race 等方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值