【模拟实现】promiseAll()

3/29/2021 面试模拟实现

# 实现思路

  1. 接收一个Promise实例数组,或具有Iterator接口的对象
  2. 如果元素不是Promise对象,则使用Promise.resolve转成Promise对象
  3. 如果全部成功,则状态变为fulfilled,返回值组成一个数组回调
  4. 只要其中一个失败了,则状态变为rejected,失败的返回值传递给catch

看下浏览器下,Promise.all()的效果:

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p1 success')
  }, 500)
})
var p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p2 success')
  }, 1000)
})
var p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('p3 fail')
  }, 500)
})
var p4 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('p4 fail')
  }, 1000)
})

Promise.all([1, 2, 3, p1, p2])
  .then(function (results) {
    console.log(results)
  }).catch(function (e){
    console.log(e)
  })

Promise.all([1, 2, 3, p3, p4])
  .then(function (results) {
    console.log(results)
  }).catch(function (e){
    console.log(e)
  })
// 0.5秒后,p3 fail
// 1秒后,[ 1, 2, 3, 'p1 success', 'p2 success' ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 代码实现

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject(new TypeError('invalid arguments!'))
    }
    let n = promises.length
    let rets = Array(n)   // resolve的返回值
    let resolvedCnt = 0   // 已经resolve的数量
    for (let i = 0; i < n; ++i) {
      Promise.resolve(promises[i])
        .then(
          value => {
            ++resolvedCnt
            rets[i] = value
            if (resolvedCnt === n) {
              return resolve(rets)
            }
          },
          reason => {
            return reject(reason)
          }
        )
    }
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 测试一下

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p1 success')
  }, 500)
})
var p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('p2 success')
  }, 1000)
})
var p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('p3 fail')
  }, 500)
})
var p4 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('p4 fail')
  }, 1000)
})

promiseAll([1, 2, 3, p1, p2])
  .then(function (results) {
    console.log(results)
  }).catch(function (e){
    console.log(e)
  })

promiseAll([1, 2, 3, p3, p4])
  .then(function (results) {
    console.log(results)
  }).catch(function (e){
    console.log(e)
  })

// 0.5秒后,p3 fail
// 1秒后,[ 1, 2, 3, 'p1 success', 'p2 success' ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Promise.all()表现一致。

Last Updated: 3/31/2021, 1:05:35 PM