思路明确手写 Promise (二):编写核心部分的 polyfill

4/20/2021 PromisePromise 源码手写 Promise

基于 上一篇 的分析梳理,我们能很容易写出核心部分的 polyfill。 包括:

  1. new Promise((resolve, reject) => {})
  2. .then(onFulfilled, onRejected)
  3. .catch(onRejected)

# 编写 Promise 核心写法的 polyfill

# Promise 构造函数

根据 已知 ,很容易写出如下代码:

const PENDING = 0
const FULFILLED = 1
const REJECTED = 2

class MyPromise {
  promiseState = PENDING
  /**
   * 需要传递给下一个 promise 的值
   * 赋值时机:
   * new Promise((resolve, reject) => {}) 调用 resolve/reject 时设置的值
   */
  promiseResult = undefined

  constructor(executor) {
    const resolve = result => {
      this.promiseResult = result
      this.promiseState = FULFILLED
    }
    const reject = result => {
      this.promiseResult = result
      this.promiseState = REJECTED
    }

    executor(resolve, reject)
  }

  then() {
    //
  }

  catch() {
    //
  }
}
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

# 处理外部函数的安全时的异常

声明异常处理函数:

function rejectWhenAbnormal(runner, reject) {
  try {
    runner()
  } catch (err) {
    reject()
  }
}
1
2
3
4
5
6
7

并使用:

class MyPromise {
  promiseState = PENDING

  constructor(executor) {
    // ...

    rejectWhenAbnormal(() => {
      executor(resolve, reject)
    }, reject)
  }

  // ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13

此时,new MyPromise((resolve, reject) => {}) 就已经支持了。

# .then 方法

根据 已知 ,很容易写出如下代码:

.catch 就是 .then 的一个变形:

class MyPromise {
  // ...

  then(onFulfilled, onRejected) {
    //
  }

  catch(onRejected) {
    return this.then(() => {}, onRejected)
  }
}
1
2
3
4
5
6
7
8
9
10
11

来看 .then 方法:

  1. 返回新的 promise
class MyPromise {
  // ...

  then(onFulfilled, onRejected) {
    return new MyPromise(() => {})
  }
}
1
2
3
4
5
6
7
  1. .then 在每一次调用的时候都会接收 onFulfilled/onRejected,将其保存起来,在当前 promise 状态变更时调用,并接收上个 promise 传过来的值;处理运行时异常
class MyPromise {
  // ...
  /**
   * { handleFulfilledAsync, handleRejectedAsync }
   * .then() 时候注册
   * promiseState 变更的时候执行
   */
  stateChangeHandlers = []

  then(onFulfilled, onRejected) {
    let nextResolve, nextReject
    const nextPromise = new MyPromise((resolve, reject) => {
      nextResolve = resolve
      nextReject = reject
    })

    // 改变 nextPromise 的状态并向其传递值
    const handleFulfilledAsync = () => {
      nextTick(() => {
        rejectWhenAbnormal(() => {
          const promiseResult = onFulfilled()
          nextResolve(promiseResult)
        }, nextReject)
      })
    }

    const handleRejectedAsync = () => {
      nextTick(() => {
        rejectWhenAbnormal(() => {
          const promiseResult = onRejected()
          nextResolve(promiseResult)
        }, nextReject)
      })
    }

    // 根据状态处理对 nextPromise 的状态变更
    if (this.promiseState === PENDING) {
      this.stateChangeHandlers.push({
        handleFulfilledAsync,
        handleRejectedAsync,
      })
    } else if (this.promiseState === FULFILLED) {
      handleFulfilledAsync()
    } else {
      handleRejectedAsync()
    }

    return nextPromise
  }
}
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
48
49
50
  1. 状态变更时,执行注册的 stateChangeHandlers
const nextTick = setTimeout

class MyPromise {
  // ...

  _promiseState = PENDING
  get promiseState() {
    return this._promiseState
  }
  set promiseState(state) {
    if (this._promiseState !== PENDING) {
      return
    }
    this._promiseState = state

    this.stateChangeHandlers.forEach(handler => {
      if (state === FULFILLED) {
        handler.handleFulfilledAsync()
      } else {
        handler.handleRejectedAsync()
      }
    })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  1. 向后面的 promise 传递值;如果传递的值是 promise,则使用这个 promise 的状态
// 改变 nextPromise 的状态并向其传递值
const handleFulfilledAsync = () => {
  nextTick(() => {
    rejectWhenAbnormal(() => {
      const nextPromiseResult = onFulfilled(this.promiseResult)
      if (isPromise(nextPromiseResult)) {
        nextPromiseResult.then(nextResolve, nextReject)
      } else {
        nextResolve(nextPromiseResult)
      }
    }, nextReject)
  })
}

const handleRejectedAsync = () => {
  nextTick(() => {
    rejectWhenAbnormal(() => {
      const nextPromiseResult = onRejected(this.promiseResult)
      if (isPromise(nextPromiseResult)) {
        nextPromiseResult.then(nextResolve, nextReject)
      } else {
        nextResolve(nextPromiseResult)
      }
    }, nextReject)
  })
}
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

上面的 handleFulfilledAsynchandleRejectedAsync 可以合并为一个函数:

// 改变 nextPromise 的状态并向其传递值
const handleFulfilledAsync = () => handleFulfilledOrRejectedAsync(onFulfilled)

const handleRejectedAsync = () => handleFulfilledOrRejectedAsync(onRejected)

const handleFulfilledOrRejectedAsync = handler => {
  nextTick(() => {
    rejectWhenAbnormal(() => {
      const nextPromiseResult = handler(this.promiseResult)
      if (isPromise(nextPromiseResult)) {
        nextPromiseResult.then(nextResolve, nextReject)
      } else {
        nextResolve(nextPromiseResult)
      }
    }, nextReject)
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# .catch 方法

class MyPromise {
  // ...

  then(onFulfilled, onRejected) {
    //
  }

  catch(onRejected) {
    return this.then(() => {}, onRejected)
  }
}
1
2
3
4
5
6
7
8
9
10
11

下一篇我们来写其他方法。

Last Updated: 10/18/2021, 5:03:42 PM