手动实现promise核心

发布时间 2023-10-12 21:41:49作者: 智勇_y

了解Promise

Promise 构造函数是 JavaScript 中用于创建 Promise 对象的内置构造函数。

Promise 构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败的状态。

起始函数执行成功时,它应该调用 resolve 函数并传递成功的结果。当起始函数执行失败时,它应该调用 reject 函数并传递失败的原因。

Promise 构造函数返回一个 Promise 对象,该对象具有以下几个方法:

  • then:用于处理 Promise 成功状态的回调函数。
  • catch:用于处理 Promise 失败状态的回调函数。
  • finally:无论 Promise 是成功还是失败,都会执行的回调函数。

实现一个能把函数放入微队列执行的函数

  • 可以利用MutationObserver的特性把函数放入微队列中执行
  • MutationObserver是一个观察器,使用的时候需要传入一个函数,当它观察到元素发生变化时会把传入的函数放入微队列中执行
// 实现把函数放入微队列执行
function runMicroTask(fn) {
  if (typeof process !== 'undefined' && typeof process.nextTick === 'function') {
    return process.nextTick(fn)
  } else if (typeof MutationObserver === 'function') {
    const ob = new MutationObserver(fn)
    const textNode = document.createTextNode('1')
    ob.observe(textNode, {
      characterData: true
    })
    textNode.data = 2
  }
}

完整实现代码

function runMicroTask(fn) {
  if (typeof process !== 'undefined' && typeof process.nextTick === 'function') {
    return process.nextTick(fn)
  } else if (typeof MutationObserver === 'function') {
    const ob = new MutationObserver(fn)
    const textNode = document.createTextNode('1')
    ob.observe(textNode, {
      characterData: true
    })
    textNode.data = 2
  }
}

// 检测一个对象是否为promise对象
function isPromiseLike(obj) {
  return !!(obj && typeof obj === 'object' && typeof obj.then === 'function')
}

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {

  /**
   * 
   * @param {Function} executor 任务执行器,立即执行
   */
  constructor(executor) {
    this._state = PENDING
    this._value = void 0
    this._handlers = []
    try {
      executor(this._resolve.bind(this), this._reject.bind(this))
    } catch (error) {
      this._reject(error)
    }
  }

  _resolve(data) {
    this._changeState(FULFILLED, data)
  }

  _reject(reason) {
    this._changeState(REJECTED, reason)
  }

  _changeState(newState, data) {
    if (this._state !== PENDING) return
    this._state = newState
    this._value = data
    this._runHandlers()
  }


  /**
   * 
   * @param {Function} executor  处理函数
   * @param {String} state   执行处理函数的状态
   * @param {Function} resolve  
   * @param {Function} reject 
   */
  _pushHandlers(executor, state, resolve, reject) {
    this._handlers.push({
      executor,
      state,
      resolve,
      reject
    })
  }

  _runHandlers() {
    if (this._state === PENDING) return
    while (this._handlers[0]) {
      const handle = this._handlers[0]
      this._runOneHandler(handle)
      this._handlers.shift()
    }
  }


  /**
   * 
   * @param {Object} handle 
   */
  _runOneHandler({ executor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) return
      if (typeof executor !== 'function') {
        this._state === FULFILLED
          ? resolve(this._value)
          : reject(this._value)
        return
      }

      try {
        const result = executor(this._value)
        if (isPromiseLike(result)) {
          result.then(resolve, reject)
        }
        resolve(result)
      } catch (error) {
        reject(error)
      }
    })
  }

  /**
   * 
   * @param {Function} onFulfilled 
   * @param {Function} onRejected 
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandlers(onFulfilled, FULFILLED, resolve, reject)
      this._pushHandlers(onRejected, REJECTED, resolve, reject)
    })
  }
}