思路明确手写 Promise (三):编写其它方法

4/20/2021 PromisePromise 源码手写 Promise

编写 Promise 其它方法。

  • .prototype.finally()
  • .resolve()
  • .reject()
  • .all()
  • .allSettled()
  • .any()
  • .race()

# .prototype.finally

MDN (opens new window)

class MyPromise {
  // ..

  finally(onFinally) {
    return this.then(
      () => {
        onFinally()
      },
      () => {
        onFinally()
      }
    )
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 静态方法

# Promise.resolve()

MDN (opens new window)

class MyPromise {
  // ..

  static resolve(val) {
    return new MyPromise((resolve, reject) => {
      if (isPromise(val)) {
        handleNextResolveOrNextRejectWithResultPromise(val, resolve, reject)
      } else {
        resolve(val)
      }
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Promise.reject()

MDN (opens new window)

class MyPromise {
  // ..

  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      if (isPromise(reason)) {
        handleNextResolveOrNextRejectWithResultPromise(reason, resolve, reject)
      } else {
        reject(reason)
      }
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Promise.all()

MDN (opens new window)

class MyPromise {
  // ..

  static all(promiseList) {
    return new MyPromise((resolve, reject) => {
      const result = []
      let resolvedCount = 0

      const tryResolveAll = () => {
        if (resolvedCount === promiseList.length) {
          resolve(result)
        }
      }

      promiseList.forEach((p, i) => {
        if (isPromise(p)) {
          handleNextResolveOrNextRejectWithResultPromise(
            p,
            val => {
              resolvedCount++
              result[i] = val
              tryResolveAll()
            },
            reject
          )
        } else {
          resolvedCount++
          result[i] = p
          tryResolveAll()
        }
      })
    })
  }
}
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

# Promise.allSettled()

MDN (opens new window)

class MyPromise {
  // ..

  static allSettled(promiseList) {
    return new MyPromise(resolve => {
      const result = []
      let resolvedCount = 0

      const tryResolveAll = () => {
        if (resolvedCount === promiseList.length) {
          resolve(result)
        }
      }

      promiseList.forEach((p, i) => {
        if (isPromise(p)) {
          handleNextResolveOrNextRejectWithResultPromise(
            p,
            val => {
              resolvedCount++
              result[i] = {
                status: 'fulfilled',
                value: val,
              }
              tryResolveAll()
            },
            reason => {
              resolvedCount++
              result[i] = {
                status: 'rejected',
                reason: reason,
              }
              tryResolveAll()
            }
          )
        } else {
          resolvedCount++
          result[i] = {
            status: 'fulfilled',
            value: p,
          }
          tryResolveAll()
        }
      })
    })
  }
}
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
38
39
40
41
42
43
44
45
46
47

# Promise.any()

MDN (opens new window)

class MyPromise {
  // ..

  static any(promiseList) {
    return new MyPromise((resolve, reject) => {
      let settled = false
      let reasonList = []
      let rejectedCount = 0

      const tryResolveAny = val => {
        if (!settled) {
          resolve(val)
          settled = true
        }
      }

      const tryRejectAny = () => {
        if (!settled && rejectedCount === promiseList.length) {
          reject(new AggregateError(reasonList, 'All Promises rejected'))
          settled = true
        }
      }

      promiseList.some((p, i) => {
        if (isPromise(p)) {
          handleNextResolveOrNextRejectWithResultPromise(
            p,
            val => {
              tryResolveAny(val)
            },
            reason => {
              rejectedCount++
              reasonList[i] = reason
              tryRejectAny()
            }
          )
          if (p.promiseState === FULFILLED) {
            return true
          }
        } else {
          tryResolveAny(p)
          return true
        }
      })
    })
  }
}
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
38
39
40
41
42
43
44
45
46
47

# Promise.race()

MDN (opens new window)

class MyPromise {
  // ..

  static race(promiseList) {
    return new MyPromise((resolve, reject) => {
      let done = false
      const tryResolveRace = value => {
        if (!done) {
          resolve(value)
          done = true
        }
      }
      const tryRejectRace = reason => {
        if (!done) {
          reject(reason)
          done = true
        }
      }
      promiseList.some(p => {
        if (isPromise(p)) {
          handleNextResolveOrNextRejectWithResultPromise(p, tryResolveRace, tryRejectRace)
          if (p.promiseState !== PENDING) {
            return true
          }
        } else {
          resolve(p)
          return true
        }
      })
    })
  }
}
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
Last Updated: 10/18/2021, 5:03:42 PM