编程语言
首页 > 编程语言> > 从零开始一个完整的promise(附源码)

从零开始一个完整的promise(附源码)

作者:互联网

实现过程详细步骤,文档传送门

源码:

// 先定义三个状态变量
const PENDING = 'pending'
const REJECTED = 'rejected'
const FULFILLED = 'fulfilled'

class MyPromise {

  state = PENDING
  value = ''      // 向后传的value值
  callbacks = []  // 回调队列

  constructor(fn) {
    if (typeof fn !== "function") {
      throw new Error('参数必须是函数')
    }
    fn(this._resolve.bind(this), this._reject.bind(this))
  }

  static resolve(data) {
    return new MyPromise(resolve => {
      resolve(data)
    })
  }
  static reject(data) {
    return new MyPromise((resolve, reject) => {
      reject(data)
    })
  }

  static all(promiseArr) {
    if (!Array.isArray(promiseArr)) {
      throw new Error('参数必须是数组')
    }
    return new MyPromise((resolve, reject) => {
      const result = []
      const Arrlength = promiseArr.length
      let tempItem
      let resolveNums = 0  //记录fulfilled实例的个数
      for (let i = 0; i < Arrlength; i++) {
        tempItem = promiseArr[i]
        if (!(tempItem instanceof MyPromise)) {
          tempItem = MyPromise.resolve(tempItem)
        }
        tempItem.then((data) => {
          resolveNums++
          result[i] = data
          // 全部都变为fulfilled,返回
          if (resolveNums === Arrlength) {
            resolve(result)
          }
        }, (data) => {
          reject(data)
        })
      }
    })
  }


  static race(promiseArr) {
    if (!Array.isArray(promiseArr)) {
      throw new Error('参数必须是数组')
    }
    return new MyPromise((resolve, reject) => {
      const Arrlength = promiseArr.length
      let tempItem
      for (let i = 0; i < Arrlength; i++) {
        tempItem = promiseArr[i]
        if (!(tempItem instanceof MyPromise)) {
          tempItem = MyPromise.resolve(tempItem)
        }
        tempItem.then((data) => {
          resolve(data)
        }, (data) => {
          reject(data)
        })
      }
    })
  }

  static any(promiseArr) {
    if (!Array.isArray(promiseArr)) {
      throw new Error('参数必须是数组')
    }
    return new MyPromise((resolve, reject) => {
      const result = []
      const Arrlength = promiseArr.length
      let tempItem
      let rejectedNums = 0  //记录rejected实例的个数
      for (let i = 0; i < Arrlength; i++) {
        tempItem = promiseArr[i]
        if (!(tempItem instanceof MyPromise)) {
          tempItem = MyPromise.resolve(tempItem)
        }
        tempItem.then(data => {
          resolve(data)
        }, data => {
          result[i] = data
          if (++rejectedNums === Arrlength) {
            reject(result)
          }
        })
      }
    })
  }
  // 捕获前边未处理的reject。
  catch(onRejected) {
    return this.then(null, onRejected)
  }

  // 无论前边promise是何种状态,都会执行的方法
  finally(fn) {
    return this.then(fn, fn)
  }

  then(onFulfilled, onRejected) {
    const _this = this;   //_this指向前一个promise对象
    return new MyPromise((resolve, reject) => {
      _this._handle({
        onFulfilled,
        onRejected,
        resolve,
        reject
      })
    })
  }



  _resolve(value) {
    if (this.state !== PENDING) {
      return
    }
    this.state = FULFILLED  //修改状态
    this.value = value      // 赋值,用于向后传递
    this.callbacks.forEach(cb => this._handle(cb))  //回调then中的注册函数
  }

  _reject(error) {
    if (this.state !== PENDING) {
      return
    }
    this.state = REJECTED  //修改状态
    this.value = error      // 赋值,用于向后传递
    this.callbacks.forEach(cb => this._handle(cb))  //回调then中的注册函数
  }
  _handle(callback) {
    // prnding状态时,注册函数入栈
    if (this.state === PENDING) {
      this.callbacks.push(callback)
      return
    }
    // 按需获取then中注册的回调函数
    const cb = this.state === FULFILLED ? callback.onFulfilled : callback.onRejected

    // 改变then返回的promise的状态,持续回调后续的then
    const cb_changeState = this.state === FULFILLED ? callback.resolve : callback.reject

    let ret

    if (cb) {
      ret = cb(this.value) //计算继续向后传递的值
      // 返回一个promise
      if (ret instanceof MyPromise) {
        ret.then((data) => {
          callback.resolve(data)
        }, (err) => {
          callback.reject(err)
        })
      } else {
        callback.resolve(ret)
      }
    } else {
      cb_changeState(this.value) //then里没有回调函数,把当前value继续向下传递
    }
  }
}

标签:resolve,tempItem,MyPromise,从零开始,promise,promiseArr,reject,data,源码
来源: https://blog.csdn.net/u013910340/article/details/118391385