手写Promise

实现步骤

  1. 创建MyPromise类
  2. 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用
  3. 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)
  4. 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
  5. 完成resolve和reject函数的状态改变(注意:需判断当前状态是否可以改变)
  6. MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值
  7. MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因
  8. 处理异步逻辑(pending状态下在then中将回调存起来)
  9. 实现then方法多次调用添加多个处理函数
  10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)
  11. 处理promise返回值各种类型情况(普通值,promise)
  12. then方法链式调用识别Promise对象自返回
  13. Promise实现捕获错误及then链式调用其他状态代码补充
  14. 将then方法的参数变为可选参数
  15. Promise.all
  16. Promise.resolve 返回一个promise
  17. finally方法 不管成功失败都会执行一次
  18. 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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// 4. 定义状态常量(成功fulfilled 失败rejected 等待pending),初始化为pending。
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

// 1 创建MyPromise类
class MyPromise {
// 2 通过构造函数constructor,在执行这个类的时候需要传递一个执行器进去并立即调用
constructor(executor) {
// 13 Promise实现捕获错误
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}

status = PENDING
// 6. MyPromise类中定义value和reason,用来储存执行器执行成功和失败的返回值
value = null
reason = null
// 9. 实现then方法多次调用添加多个处理函数 初始化回调为数组依次执行
successCallback = []
failCallback = []
// 3. 定义resolve和reject(定义为箭头函数:避免直接调用时this指向全局window问题)
resolve = value => {
// 5. 完成resolve函数的状态改变(注意:需判断当前状态是否可以改变)
// 判断当前状态是否可改变
if (this.status !== PENDING) return
// 改变当前状态
this.status = FULFILLED
// 保存返回值
this.value = value
// 执行成功回调
while (this.successCallback.length) {
this.successCallback.shift()(this.value)
}
}
reject = reason => {
// 5. 完成reject函数的状态改变(注意:需判断当前状态是否可以改变)
// 判断当前状态是否可改变
if (this.status !== PENDING) return
// 改变当前状态
this.status = REJECTED
// 保存返回值
this.reason = reason
// 执行失败回调
while (this.failCallback.length) {
this.failCallback.shift()(this.reason)
}
}

// 7. MyPromise类中添加then方法,成功回调有一个参数 表示成功之后的值;失败回调有一个参数 表示失败后的原因
then(successCallback, failCallback) {
// 14 将then方法的参数变为可选参数
successCallback = successCallback ? successCallback : value => this.value
failCallback = failCallback ? failCallback : reason => {
throw this.reason
}
// 10. 实现then方法链式调用(写一个函数方法专门判断回调的结果是普通值还是promise,then方法返回的仍然是一个promise)
let promise2 = new MyPromise((resolve, reject) => {
// 判断当前状态 执行对应回调 异步情况下存储当前回调等待执行
if (this.status === FULFILLED) {
// 异步
setTimeout(() => {
// 13 then方法捕获错误
try {
// 异步获取到promise2
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else if (this.status === REJECTED) {
// 异步
setTimeout(() => {
// 13 then方法捕获错误
try {
// 异步获取到promise2
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else {
// 8. 处理异步逻辑(pending状态下在then中将回调存起来)
this.successCallback.push(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.failCallback.push(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
})
return promise2
}

// 17. finally方法 不管成功失败都会执行一次
finally(callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.reject(callback()).then(() => {
throw reason
})
})
}

// 18. catch
catch(failCallback) {
return this.then(undefined, failCallback)
}

// 15. Promise.all
static all(array) {
let result = []
let index
return new Promise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
}

for (let i = 0; i < array.length; i++) {
let current = array[i]
if (current instanceof MyPromise) {
current.then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, array[i])
}
}
})
}

// 16. Promise.resolve 返回一个promise
static resolve(value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
}

// 处理promise返回值各种类型情况(普通值,promise)
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}

手写Promise
https://yifengtingyu.cn/2024/04/22/手写Promise/
作者
依风听雨
发布于
2024年4月22日
许可协议