手写 promise

1.Promise 构造函数

  • 参数 构造函数接受一个函数作为参数,该函数有两个参数也是函数
  • resolve 函数用于将 Promise 对象的状态从 pending 变为 fulfilled
  • reject 函数用于将 Promise 对象的状态从 pending 变为 rejected
  • 状态三个:pending、fulfilled 和 rejected,状态不可逆
  • 构造函数: executor 函数中,所以 promise 本身是同步的,then\catch 才是异步

下面是一个Promise构造器的简单实现

 1const PENDING = 'pending'
 2const FULFILLED = 'fulfilled'
 3const REJECTED = 'rejected'
 4
 5class MyPromise {
 6    constructor(executor) {
 7        this.status = PENDING
 8        this.reason = undefined
 9
10        const resolve = (value) => {
11            if (this.status !== PENDING) return
12            this.status = FULFILLED
13            this.reason = value
14        }
15
16        const reject = (reason) => {
17            if (this.status !== PENDING) return
18            this.status = REJECTED
19            this.reason = reason
20        }
21
22        try {
23            executor(resolve, reject)
24        } catch (error) {
25            reject(error)
26        }
27    }
28}

2.then 方法

  • 参数,分别是 onFulfilledonRejected,这两个参数都是函数
  • 链式调用,因为返回一个新的 Promise 对象,该对象的状态由 onFulfilled 和 onRejected 的返回值决定
  • 微任务,把 onFulfilled、onRejected、resolve、reject 存起来,等到 Promise 的状态改变时,再执行。可以使用数组来存储这些函数,当状态改变时,依次执行这些函数
 1const PENDING = 'pending'
 2const FULFILLED = 'fulfilled'
 3const REJECTED = 'rejected'
 4
 5class MyPromise {
 6    #status = PENDING 
 7    #reason = null 
 8    #handlers = [] 
 9
10    constructor(executor) {
11        const resolve = (reason) => {
12            this.#changeState(FULFILLED, reason)
13        }
14        const reject = (reason) => {
15            this.#changeState(REJECTED, reason)
16        }
17        try {
18            executor(resolve, reject)
19        } catch (error) {
20            reject(error)
21        }
22    }
23    then(onFulfilled, onRejected) {
24        return new MyPromise((resolve, reject) => {
25            this.#handlers.push({
26                onFulfilled,
27                onRejected,
28                resolve,
29                reject,
30            })
31            this.#run()
32        })
33    }
34
35    
36     * promise 状态发生改变时记录状态及结果并执行run函数
37     * @param {*} state 状态
38     * @param {*} reason 结果
39     * @returns
40     */
41    #changeState(state, reason) {
42        if (this.#status !== PENDING) return
43        this.#status = state
44        this.#reason = reason
45        this.#run()
46    }
47    
48     * run函数辅助then函数返回的promise对象有结果时
49     * 遍历执行所有onFulfilledonRejected 并把结果传递给下一个promise对象
50     * @returns
51     */
52    #run() {
53        if (this.#status === PENDING) return
54        while (this.#handlers.length) {
55            const { onFulfilled, onRejected, resolve, reject } =
56                this.#handlers.shift()
57            let fn = this.#status === FULFILLED ? onFulfilled : onRejected
58            this.#runFn(fn, resolve, reject)
59        }
60    }
61    
62     * setTimeout执行模拟微任务的执行环境
63     * @param {*} fn onFulfilled | onRejected
64     * @param {*} resolve 通过resolve传递给下一个promise对象
65     * @param {*} reject
66     *
67     */
68    #runFn(fn, resolve, reject) {
69        setTimeout(() => {
70            if (typeof fn !== 'function') {
71                let settled = this.#status === FULFILLED ? resolve : reject
72                settled(this.#reason)
73                return
74            }
75            try {
76                const res = fn(this.#reason)
77                
78                resolve(res)
79            } catch (error) {
80                reject(error)
81            }
82        }, 0)
83    }
84}
85
86const p = new MyPromise((resolve, reject) => {
87    console.log('promise')
88    setTimeout(() => {
89        reject('123')
90    }, 1000)
91})
92p.then(
93    (res) => {
94        console.log(res)
95    },
96    (err) => {
97        console.log(err, 'err')
98    }
99)
100p.then(
101    (res) => {
102        console.log(res)
103    },
104    (err) => {
105        console.log(err, 'err2')
106    }
107)

3.catch 方法

  • catch 方法是状态为 REJECTED 时的处理函数
  • 和 then 不同的是 只接受一个 onRejected 参数 下面是利用 then 实现
 1catch(onRejected) {
 2  return this.then(null, onRejected);
 3}

4.resolve 方法

  • resolve 方法返回一个状态为 FULFILLED 的 promise 对象
  • 接受一个参数 value
  • 如果 value 是一个 promise 对象,则返回该 promise 对象
  • 否则,返回一个状态为 FULFILLED 的 promise 对象,其值为 value
 1static resolve(value) {
 2    if (value instanceof MyPromise) return value
 3  return new MyPromise((resolve, reject) => {
 4    resolve(value)
 5  })
 6}

5.reject 方法

  • reject 方法返回一个状态为 REJECTED 的 promise 对象
  • 接受一个参数 reason
 1static reject(reason) {
 2  return new MyPromise((resolve, reject) => {
 3    reject(reason)
 4  })
 5}

6.finally 方法

  • finally 方法接受一个回调函数作为参数
  • 无论 promise 对象的状态是 FULFILLED 还是 REJECTED,都会执行该回调函数
  • finally 方法返回一个 promise 对象,其状态和值与原 promise 对象相同
  • 利用 then, 失败和成功都执行一下回调
 1finally(onFinally) {
 2  return this.then(
 3    value => MyPromise.resolve(onFinally()).then(() => value),
 4    reason => MyPromise.resolve(onFinally()).then(() => {
 5      throw reason
 6    })
 7  )
 8}

7.all 方法

  • all 方法接受一个 promise 对象的数组作为参数
  • 返回值:有一个失败,则返回失败,否则返回成功
  • 往往项目中是所有成功或者失败的结果都要,就使用 allSettled
 1static all(promiseArr) {
 2    if (typeof promiseArr[Symbol.iterator] !== 'function') {
 3        throw new Error('参数必须是可迭代对象')
 4    }
 5  return new MyPromise((resolve, reject) => {
 6    let result = []
 7    let count = 0
 8    for (let i = 0; i < promiseArr.length; i++) {
 9      promiseArr[i].then(res => {
10        result[i] = res
11        count++
12        if (count === promiseArr.length) {
13          resolve(result)
14        }
15      }, err => {
16        reject(err)
17      })
18    }
19  })
20}

8. allSettled 方法

  • allSettled 方法接受一个 promise 对象的数组作为参数
  • 返回值: promise 对象,其状态为 FULFILLED,值为一个数组,数组中的每个元素都是一个对象,表示每个 promise 对象的状态和值
 1  static allSettled(promiseArr) {
 2    if (typeof promiseArr[Symbol.iterator] !== 'function') {
 3      throw new Error('参数必须是可迭代对象')
 4    }
 5    return new MyPromise((resolve, reject) => {
 6      let result = []
 7      let count = 0
 8      for (let i = 0; i < promiseArr.length; i++) {
 9        promiseArr[i].then(res => {
10          result[i] = { status: 'fulfilled', value: res }
11        }, err => {
12          result[i] = { status: 'rejected', reason: err }
13        })
14      }
15    })
16  }

9.race 方法

  • race 方法接受一个 promise 对象的数组作为参数
  • 返回值:返回最先执行完的 promise 对象的结果, 无论成功、失败
 1static race(promiseArr) {
 2    if (typeof promiseArr[Symbol.iterator] !== 'function') {
 3      throw new Error('参数必须是可迭代对象')
 4    }
 5    return new MyPromise((resolve, reject) => {
 6      for (let i = 0; i < promiseArr.length; i++) {
 7        promiseArr[i].then(res => {
 8          resolve(res) 
 9        }, err => {
10          reject(err) 
11        })
12      }
13    })
14  }

10. any

  • any 方法接受一个 promise 对象的数组作为参数
  • 返回值:返回最先成功 promise 对象的结果, 如果全部失败则返回一个失败的 promise 对象
 1  static any(promiseArr) {
 2    if (typeof promiseArr[Symbol.iterator] !== 'function') {
 3      throw new Error('参数必须是可迭代对象')
 4    }
 5    return new MyPromise(async(resolve, reject) => {
 6      const result = []
 7      for (let i = 0; i < promiseArr.length; i++) {
 8        try {
 9          const res = await promiseArr[i]
10          resolve(res)
11        } catch (error) {
12          result[i] = { status: 'rejected', reason: error }
13          if (i === promiseArr.length - 1) {
14            reject(result)
15          }
16        }
17      }
18
19    })
20  }

完整代码

 1const PENDING = 'pending'
 2const FULFILLED = 'fulfilled'
 3const REJECTED = 'rejected'
 4
 5class MyPromise {
 6  #status = PENDING; 
 7  #reason = null; 
 8  #handlers = []; 
 9
10  constructor(executor) {
11    const resolve = (reason) => {
12      this.#changeState(FULFILLED, reason)
13    }
14    const reject = (reason) => {
15      this.#changeState(REJECTED, reason)
16    }
17    try {
18      executor(resolve, reject);
19    } catch (error) {
20      reject(error);
21    }
22  }
23  then(onFulfilled, onRejected) {
24    return new MyPromise((resolve, reject) => {
25      this.#handlers.push({
26        onFulfilled,
27        onRejected,
28        resolve,
29        reject
30      });
31      this.#run();
32    });
33
34  }
35
36  catch(onRejected) {
37    return this.then(null, onRejected);
38  }
39  finally(onFinally) {
40    return this.then(
41      value => MyPromise.resolve(onFinally()).then(() => value),
42      reason => MyPromise.resolve(onFinally()).then(() => {
43        throw reason
44      })
45    )
46  }
47
48  static reject(reason) {
49    return new MyPromise((resolve, reject) => {
50      reject(reason)
51    })
52  }
53
54  static resolve(value) {
55    if (value instanceof MyPromise) return value
56    return new MyPromise((resolve, reject) => {
57      resolve(value)
58    })
59  }
60
61  static all(promiseArr) {
62    if (typeof promiseArr[Symbol.iterator] !== 'function') {
63      throw new Error('参数必须是可迭代对象')
64    }
65    return new MyPromise((resolve, reject) => {
66      let result = []
67      let count = 0
68      for (let i = 0; i < promiseArr.length; i++) {
69        promiseArr[i].then(res => {
70          result[i] = res
71          count++
72          if (count === promiseArr.length) {
73            resolve(result)
74          }
75        }, err => {
76          reject(err) 
77        })
78      }
79    })
80  }
81
82  static race(promiseArr) {
83    if (typeof promiseArr[Symbol.iterator] !== 'function') {
84      throw new Error('参数必须是可迭代对象')
85    }
86    return new MyPromise((resolve, reject) => {
87      for (let i = 0; i < promiseArr.length; i++) {
88        promiseArr[i].then(res => {
89          resolve(res) 
90        }, err => {
91          reject(err) 
92        })
93      }
94    })
95  }
96
97  static allSettled(promiseArr) {
98    if (typeof promiseArr[Symbol.iterator] !== 'function') {
99      throw new Error('参数必须是可迭代对象')
100    }
101    return new MyPromise((resolve, reject) => {
102      let result = []
103      for (let i = 0; i < promiseArr.length; i++) {
104        promiseArr[i].then(res => {
105          result[i] = { status: 'fulfilled', value: res }
106        }, err => {
107          result[i] = { status: 'rejected', reason: err }
108        })
109      }
110      resolve(result)
111    })
112  }
113
114  static any(promiseArr) {
115    if (typeof promiseArr[Symbol.iterator] !== 'function') {
116      throw new Error('参数必须是可迭代对象')
117    }
118    return new MyPromise(async (resolve, reject) => {
119      const result = []
120      for (let i = 0; i < promiseArr.length; i++) {
121        try {
122          const res = await promiseArr[i]
123          resolve(res)
124        } catch (error) {
125          result[i] = { status: 'rejected', reason: error }
126          if (i === promiseArr.length - 1) {
127            reject(result)
128          }
129        }
130      }
131
132    })
133
134  }
135
136  
137   * promise 状态发生改变时记录状态及结果并执行run函数
138   * @param {*} state 状态
139   * @param {*} reason 结果
140   * @returns 
141   */
142  #changeState(state, reason) {
143    if (this.#status !== PENDING) return;
144    this.#status = state;
145    this.#reason = reason;
146    this.#run();
147  }
148  
149   * run函数辅助then函数返回的promise对象有结果时
150   * 遍历执行所有onFulfilledonRejected 并把结果传递给下一个promise对象
151   * @returns 
152   */
153  #run() {
154    if (this.#status === PENDING) return;
155    while (this.#handlers.length) {
156      const { onFulfilled, onRejected, resolve, reject } = this.#handlers.shift();
157      let fn = this.#status === FULFILLED ? onFulfilled : onRejected;
158      this.#runFn(fn, resolve, reject);
159    }
160  }
161  
162   * setTimeout执行模拟微任务的执行环境
163   * @param {*} fn onFulfilled | onRejected
164   * @param {*} resolve 通过resolve传递给下一个promise对象
165   * @param {*} reject 
166   * 
167   */
168  #runFn(fn, resolve, reject) {
169    setTimeout(() => {
170      if (typeof fn !== 'function') {
171        let settled = this.#status === FULFILLED ? resolve : reject;
172        settled(this.#reason)
173        return
174      }
175      try {
176        const res = fn(this.#reason);
177        
178        resolve(res)
179      } catch (error) {
180        reject(error)
181      }
182    }, 0)
183  }
184}
个人笔记记录 2021 ~ 2025