# MyPromise 类

Promise 是一个类,使用时需要 new 一个 Promise 的实例。

# 三个状态

  • pending:等待状态
  • fulfilled:执行成功状态
  • rejected:执行失败状态

其中,状态流程为:pending->fulfilled 或者 pending->rejected

代码如下:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

# 构造函数及其参数

Promise 使用代码:

new Promise((resolve, reject) => {
	resolve()
})

new 一个 Promise 的实例的时候,会执行构造函数,同时也会立即执行传入的回调函数。

MyPromise 代码:

// 实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    executor()
  }

  status = PENDING
  value = null // 执行成功返回值
  onFulfilledCallbacks = [] // 成功状态:回调函数缓存队列
  reason = null // 执行失败原因
  onRejectedCallbacks = [] // 失败状态:回调函数缓存队列
}
// 使用
new MyPromise((resolve, reject) => {
  // 状态变更
  resolve()
})
  • new MyPromise 实例,传入执行函数实参赋值给形参 executor
  • 形参 executor 获取实参值后立即执行
  • executor 函数参数 resolve 和 reject 通过 MyPromise 内部类成员变量进行赋值
// 实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject)
    } catch(err) {
      this.reject(err)
    }
  }

  status = PENDING
  value = null // 执行成功返回值
  onFulfilledCallbacks = [] // 成功状态:回调函数缓存队列
  reason = null // 执行失败原因
  onRejectedCallbacks = [] // 失败状态:回调函数缓存队列

  resolve = () => {}
  reject = () => {}
}
// 使用
new MyPromise((resolve, reject) => {
  // 状态变更
  resolve()
})

# resolve 和 reject

executor 函数通过 resolve 或者 reject 对内部状态进行变更。

  • resolve: pendig -> fulfilled
  • reject: pending -> rejected

实现代码:

// 实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject)
  }

  status = PENDING
  value = null // 执行成功返回值
  onFulfilledCallbacks = [] // 成功状态:回调函数缓存队列
  reason = null // 执行失败原因
  onRejectedCallbacks = [] // 失败状态:回调函数缓存队列

  resolve = (value) => {
    if (this.status === PENDING) {
      // 状态变更
      this.status = FULFILLED
      this.value = value
      // 执行缓存队列中的函数
      while(this.onFulfilledCallbacks.length) {
        this.onFulfilledCallbacks.shift()(value)
      }
    }
  }

  reject = (reason) => {
    if (this.status === PENDING) {
      // 状态变更
      this.status = REJECTED
      this.reason = reason
      // 执行缓存队列中的函数
      while(this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.shift()(reason)
      }
    }
  }
}

# then

then 方法主要执行以下逻辑:

  • fulfilled 状态:执行 onFulfilled 函数。
  • rejected 状态:执行 onRejected 函数。
  • pending 状态:如 resolve 是在异步调用的场景,需要将 onFulfilled 和 onRejected 函数进行缓存。
// 实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.reject)
  }

  status = PENDING
  value = null // 执行成功返回值
  onFulfilledCallbacks = [] // 成功状态:回调函数缓存队列
  reason = null // 执行失败原因
  onRejectedCallbacks = [] // 失败状态:回调函数缓存队列

  resolve = (value) => {
    if (this.status === PENDING) {
      // 状态变更
      this.status = FULFILLED
      this.value = value
      // 执行缓存队列中的函数
      while(this.onFulfilledCallbacks.length) {
        this.onFulfilledCallbacks.shift()(value)
      }
    }
  }
  reject = (reason) => {
    if (this.status === PENDING) {
      // 状态变更
      this.status = REJECTED
      this.reason = reason
      // 执行缓存队列中的函数
      while(this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.shift()(reason)
      }
    }
  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    switch(this.status) {
      case PENDING:
        // resolve 或者 reject 在异步函数中调用,需要缓存起来
        this.onFulfilledCallbacks.push(onFulfilled)
        this.onRejectedCallbacks.push(onRejected)
        break;
      case FULFILLED:
        onFulfilled(this.value)
        break;
      case REJECTED:
        onRejected(this.reason)
        break;
      default:
        break;
    }
  }
}

至此,一个小型的 Promise 已经成型,使用下:

// 同步
const p = new MyPromise((resolve, reject) => {
  resolve('aa')
})
p.then(res => {
  console.log(res); // aa
})

// 异步
const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('bb')
  }, 10);
})
p1.then(res => {
  console.log('then1');
})
p1.then(res => {
  console.log("then2");
})
// then1 then2

# then 链式调用

then 链式调用实际是在 then 函数内部又返回一个新的 Promise,通过对上一个 then 返回值的判断,将值穿透到下一个 then 中。

修改 then 方法:

// ...

class MyPromise {
  // ...

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    const p2 = new MyPromise((resolve, reject) => {
      // 封装上一个 then 的 onFulfilled
      const fulfilled = () => {
        queueMicrotask(() => {
          // 放入微任务,不然 p2 还未完成初始化
          const x = onFulfilled(this.value)
          resolvePromise(p2, x, resolve, reject)
        })
      }
      // 封装上一个 then 的 onRejected
      const rejected = () => {
        queueMicrotask(() => {
          // 放入微任务,不然 p2 还未完成初始化
          const x = onRejected(this.reason)
          resolvePromise(p2, x, resolve, reject)
        })
      }

      switch (this.status) {
        case PENDING:
          // resolve 或者 reject 在异步函数中调用,需要缓存起来
          this.onFulfilledCallbacks.push(fulfilled)
          this.onRejectedCallbacks.push(rejected)
          break;
        case FULFILLED:
          fulfilled()
          break;
        case REJECTED:
          rejected()
          break;
        default:
          break;
      }
    })

    return p2
  }
}


// 该函数用于获取上一个 then 的返回值,并更改新 MyPromise 的状态
function resolvePromise(p2, x, resolve, reject) {
  // 判断返回值是否为自身,防止循环调用
  if (p2 === x) {
    throw new Error('cycle promise call')
  }

  if (x === null) {
    return resolve(x)
  }

  if (typeof x === 'function' || typeof x === 'object') {
      // 获取 then 函数
      let then
      try {
        then = x.then  
      } catch (err) {
        reject(err)
      }

     // then 是一个函数
     if (typeof then === 'function') {
        let called = false // 是否调用标志,防止重复调用
        try {
          then.call(x, res => {
            if(called) return
            called = true
            resolvePromise(p2, res, resolve, reject)
          }, err => {
            if(called) return
            called = true
            reject(err)
          })
        } catch {
          if(called) return
          called = true
          reject(err)
        }
    } else {
        // 对象,直接执行
        resolve(x)
    }
  } else {
    // 普通值,直接 resolve,变更 p2 的状态
    resolve(x)
  }
}

执行代码,测试链式调用:

const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('aa')
  }, 0);
})
p.then(res => {
  console.log('then1', res);
  return 'bb'
}).then(res => {
  console.log('then2', res);
  return new MyPromise((resolve, reject) => {
    resolve('cc')
  })
}).then(res => {
  console.log('then3', res);
})
// then1 aa
// then2 bb
// then3 cc

执行代码,测试返回值为自身:

const promise = new MyPromise((resolve, reject) => {
  resolve('success')
})

const p1 = promise.then(value => {
  console.log(1)
  return p1
})

// 运行的时候会走reject
p1.then(value => {
  console.log(2)
}, reason => {
  console.log(3)
})
// 1
//  cycle promise call

# 完善代码,添加 try/catch:

// 实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (error) {
      this.reject(error)
    }
  }

  status = PENDING
  value = null // 执行成功返回值
  onFulfilledCallbacks = [] // 成功状态:回调函数缓存队列
  reason = null // 执行失败原因
  onRejectedCallbacks = [] // 失败状态:回调函数缓存队列

  resolve = (value) => {
    if (this.status === PENDING) {
      // 状态变更
      this.status = FULFILLED
      this.value = value
      // 执行缓存队列中的函数
      while (this.onFulfilledCallbacks.length) {
        this.onFulfilledCallbacks.shift()(value)
      }
    }
  }
  reject = (reason) => {
    if (this.status === PENDING) {
      // 状态变更
      this.status = REJECTED
      this.reason = reason
      // 执行缓存队列中的函数
      while (this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.shift()(reason)
      }
    }
  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    const p2 = new MyPromise((resolve, reject) => {
      // 封装上一个 then 的 onFulfilled
      const fulfilled = (value) => {
        try {
          queueMicrotask(() => {
            // 放入微任务,不然 p2 还未完成初始化
            const x = onFulfilled(value)
            resolvePromise(p2, x, resolve, reject)
          })
        } catch (error) {
          reject(error)
        }
      }
      // 封装上一个 then 的 onRejected
      const rejected = (reason) => {
        try {
          queueMicrotask(() => {
            // 放入微任务,不然 p2 还未完成初始化
            const x = onRejected(reason)
            resolvePromise(p2, x, resolve, reject)
          })
        } catch (error) {
          reject(error)
        }
      }

      switch (this.status) {
        case PENDING:
          // resolve 或者 reject 在异步函数中调用,需要缓存起来
          this.onFulfilledCallbacks.push(fulfilled)
          this.onRejectedCallbacks.push(rejected)
          break;
        case FULFILLED:
          fulfilled(this.value)
          break;
        case REJECTED:
          rejected(this.reason)
          break;
        default:
          break;
      }
    })

    return p2
  }
}

function resolvePromise(p2, x, resolve, reject) {
  // 判断返回值是否为自身,防止循环调用
  if (p2 === x) {
    throw new Error('cycle promise call')
  }

  if (x !== null && (typeof x === 'function' || typeof x === 'object') {
    // 获取 then 函数
    let then
    try {
      then = x.then
    } catch (err) {
      return reject(err)
    }

    // then 是一个函数
    if (typeof then === 'function') {
      let called = false // 是否调用标志,防止重复调用
      try {
        then.call(x, res => {
          if (called) return
          called = true
          resolvePromise(p2, res, resolve, reject)
        }, err => {
          if (called) return
          called = true
          reject(err)
        })
      } catch {
        if (called) return
        called = true
        reject(err)
      }
    } else {
      // 对象,直接执行
      resolve(x)
    }
  } else {
    // 普通值,直接 resolve,变更 p2 的状态
    resolve(x)
  }
}

# catch 实现

class MyPromise {
  // ...
  catch(fn) {
    return this.then(null, fn)
  }
}

# Promise.all、Promise.race、Promise.resolve、Promise.reject 实现

MyPromise.resolve = function (val) {
  return new Promise((resolve, reject) => {
    resolve(val)
  })
}

MyPromise.reject = function (val) {
  return new Promise((resolve, reject) => {
    reject(val)
  })
}

MyPromise.all = function (promises = []) {
  return new MyPromise((resolve, reject) => {
    const arr = []
    for (let i = 0; i < promises.length; i++) {
      promises[i].then((res) => {
        arr[i] = res
        if (arr.length === promises.length) {
          return resolve(arr)
        }
      }, reject)
    }
  })
}

MyPromise.race = function (promises = []) {
  return new MyPromise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject)
    }
  })
}