# 实现 Promise

# Promise 简介

# Promise.resolve

  • 参数是以 Promise 的实例,那么 Promise.resolve 将不做任何修改,原封不动的返回这个实例。
  • 如果参数是一个原始值,或者是一个不具备 then 方法的对象,则 Promise.resolve 返回一个新的 Promise,状态为 resolved。

# Promise.all

  • Promise.all 方法(p)接受一个数组作为参数,数组的每一项都是 Promise 的实例(p1, p2, p3),如果不是,就会调用 Promise.resolve 将参数转为 Promise 实例,再进行下一步处理。
  • 返回值组成一个数组。
  • p1、p2、p3 中如果有一个被 rejected,那么 p 的状态就变成 rejected,此时第一个 reject 的实例返回值,会传递给 p 的回调函数。

# Promise.race

  • Promise.race 参数和 Promise.all 一样,如果不是 Promise 实例,就转为 Promise 实例。
  • 返回最先改变状态的 Promise 实例的返回值。

# 代码实现

class Promise {
  constructor(fn) {
    /**
     * 三种状态
     * pending  进行中
     * fulfilled  已成功
     * rejected  已失败
     */
    this.status = 'pending'
    this.resolveList = [] // 成功后回调函数
    this.rejectList = [] // 失败后回调函数

    fn(this.resolve.bind(this), this.reject.bind(this))
  }
  then(scb, fcb) {
    if (scb) {
      this.resolveList.push(scb)
    }
    if (fcb) {
      this.rejectList.push(fcb)
    }
    return this
  }
  catch(cb) {
    if (cb) {
      this.rejectList.push(cb)
    }
    return this
  }
  resolve(data) {
    if (this.status !== 'pending') return
    this.status = 'fulfilled'
    setTimeout(() => {
      this.resolveList.forEach((s) => {
        data = s(data)
      })
    }, 0)
  }
  reject(err) {
    if (this.status !== 'pending') return
    this.status = 'rejected'
    setTimeout(() => {
      this.rejectList.forEach((f) => {
        err = f(err)
      })
    }, 0)
  }

  // 实现 Promise.resolve
  static resolve(data) {
    if (data instanceof Promise) {
      return data
    } else {
      return new Promise((resolve, reject) => {
        resolve(data)
      })
    }
  }
  // 实现 Promise.reject
  static reject(err) {
    if (err instanceof Promise) {
      return err
    } else {
      return new Promise((resolve, reject) => {
        reject(err)
      })
    }
  }
  // 实现 Promise.all
  static all(promises) {
    return new Promise((resolve, reject) => {
      let promiseCount = 0
      let promisesLength = promises.length
      let result = []
      for (let i = 0; i < promises.length; i++) {
        // promises[i] 可能不是 Promise 类型,可能不存在 then 方法,中间如果出错,直接返回错误
        Promise.resolve(promises[i]).then(
          (res) => {
            promiseCount++
            // 注意这是赋值应该用下标去赋值而不是用 push,因为毕竟是异步的,哪个 promise 先完成还不一定
            result[i] = res
            if (promiseCount === promisesLength) {
              return resolve(result)
            }
          },
          (err) => {
            return reject(err)
          }
        )
      }
    })
  }
  // 实现 Promise.race
  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i < promises.length; i++) {
        Promise.resolve(promises[i]).then(
          (res) => {
            return resolve(res)
          },
          (err) => {
            return reject(err)
          }
        )
      }
    })
  }
}

# 测试

# Promise.then

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('resolve')
    resolve(222)
  }, 1000)
})

p.then((data) => {
  setTimeout(() => {
    console.log('data', data)
  })
  return 3333
})
  .then((data2) => {
    console.log('data2', data2)
  })
  .catch((err) => {
    console.error('err', err)
  })

# Promise.reject

const p1 = Promise.reject('出错了')
p1.then(null, function (s) {
  console.log(s) // 出错了
})

# Promise.all & Promise.race

const q1 = new Promise((resolve, reject) => {
  resolve('hello')
})
const q2 = new Promise((resolve, reject) => {
  resolve('world')
})

Promise.all([q1, q2]).then((res) => {
  console.log('all:', res) // [ 'hello', 'world' ]
})
Promise.race([q1, q2]).then((res) => {
  console.log('race:', res) // hello
})
Last Updated: 3/22/2022, 6:47:54 PM