Skip to content

手写 Promise

手写 Promise.all() | MDN

TIP

Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输入,并且只返回一个 Promise 实例, 那个输入的所有 promise 的 resolve 回调的结果是一个数组。 Promise 的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。

ts
const promise1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(3)
  }, 300)
})

const promise2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(2)
  }, 200)
})

const promise3 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(1)
  }, 100)
})

/**
 * 实现 Promise.all()
 * @param promises
 */
function promiseAll(promises: Promise<any>[]) {
  const results = []

  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises))
      return reject(new TypeError('参数应当是一个数组'))

    let resolvedCounter = 0
    for (let i = 0; i < promises.length; i++) {
      const p = promises[i]
      Promise.resolve(p).then(
        (res) => {
          resolvedCounter++
          results[i] = res // [3, 2, 1]
          // results.push(res); // [1, 2, 3]

          if (resolvedCounter === promises.length)
            return resolve(results)
        },
        (reason) => {
          return reject(reason)
        },
      )
    }
  })
}

async function test() {
  const promiseArr = [promise1, promise2, promise3]
  const ans = await promiseAll(promiseArr)
  console.log(ans)
}

test()
const promise1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(3)
  }, 300)
})

const promise2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(2)
  }, 200)
})

const promise3 = new Promise((resolve) => {
  setTimeout(() => {
    resolve(1)
  }, 100)
})

/**
 * 实现 Promise.all()
 * @param promises
 */
function promiseAll(promises: Promise<any>[]) {
  const results = []

  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises))
      return reject(new TypeError('参数应当是一个数组'))

    let resolvedCounter = 0
    for (let i = 0; i < promises.length; i++) {
      const p = promises[i]
      Promise.resolve(p).then(
        (res) => {
          resolvedCounter++
          results[i] = res // [3, 2, 1]
          // results.push(res); // [1, 2, 3]

          if (resolvedCounter === promises.length)
            return resolve(results)
        },
        (reason) => {
          return reject(reason)
        },
      )
    }
  })
}

async function test() {
  const promiseArr = [promise1, promise2, promise3]
  const ans = await promiseAll(promiseArr)
  console.log(ans)
}

test()

答案是 [3, 2, 1]

如果使用 push 而非 results[i] = res;,则是 [1, 2, 3]