-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathMyPromise.js
266 lines (252 loc) · 9.2 KB
/
MyPromise.js
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// 用常量定义promise的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(execurte) {
// 默认状态是等待
this.status = PENDING
// 成功的回调默认值
this.value = undefined
// 失败的回调默认值
this.resaon = undefined
// 成功的回调队列,可以多次then,所以存在多个定义为数组
this.resolveCallBacks = []
// 失败的回调
this.rejecteCallBacks = []
// 针对执行器进行异常处理
try {
execurte(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// 成功时候的回调
resolve = (value) => {
queueMicrotask(() => {
if (this.status === PENDING) {
this.status = FULFILLED; // 修改状态
this.value = value;
this.resolveCallBacks.forEach((fn) => fn(this.value)); // 成功的回调
}
})
}
// 失败时候的回调
reject = (resaon) => {
queueMicrotask(() => {
if (this.status === PENDING) {
this.status = REJECTED; // 修改状态
this.resaon = resaon;
this.rejecteCallBacks.forEach((fn) => fn(this.resaon)); // 失败的回调
}
})
}
// then方法
then = (resolveCallBack, rejecteCallBack) => {
// 如果传递空值,则默认向后传递所以添加一个默认情况
resolveCallBack = resolveCallBack ? resolveCallBack : value => value;
// 参数可选
rejecteCallBack = rejecteCallBack ? rejecteCallBack : reason => { throw reason };
let p = new MyPromise((resolve, reject) => {
// 处理不同的返回,如果是正常值直接返回,如果是Promise对象,则返回一个Promise供继续调用
// 成功
if (this.status === FULFILLED) {
// 开启一个微任务,等待p结果的返回。否则程序限制性后返回p的值
// 针对执行的函数进行异常处理
queueMicrotask(() => {
try {
let callbackValue = resolveCallBack(this.value)
this._returnValue(p, callbackValue, resolve, reject)
} catch (error) {
reject(error)
}
})
// 失败
} else if (this.status === REJECTED) {
queueMicrotask(() => {
try {
let callbackValue = rejecteCallBack(this.resaon)
this._returnValue(p, callbackValue, resolve, reject)
} catch (error) {
reject(error)
}
})
// 等待过程
} else {
// 判断为等待状态的情况,存储任务然后后续执行
// 存储成功的任务
this.resolveCallBacks.push(() => {
queueMicrotask(() => {
try {
let callbackValue = resolveCallBack(this.value)
this._returnValue(p, callbackValue, resolve, reject)
} catch (error) {
reject(error)
}
})
})
// 存储失败的情况
this.rejecteCallBacks.push(() => {
queueMicrotask(() => {
try {
let callbackValue = rejecteCallBack(this.resaon)
this._returnValue(p, callbackValue, resolve, reject)
} catch (error) {
reject(error)
}
})
})
}
})
return p
}
// 注册一个非静态的方法,catch收集错误信息
catch(rejecteCallBack) {
return this.then(undefined, rejecteCallBack)
}
// 注册一个非静态的方法,无论成功或者失败finally都会执行
finally(callback) {
return this.then((value) => {
return MyPromise.resolve(callback()).then(() => value)
}, (resaon) => {
return MyPromise.resolve(callback()).then(() => { throw resaon })
})
}
// then可能返回一个普通值,也可能返回一个 Promise,一个内置工具
/**
*
* @param {*} p 当前在运行的Promise
* @param {*} callbackValue 返回值(then出来的值)
* @param {*} resolve 成功回调
* @param {*} reject 失败回调
* @returns
*/
_returnValue(p, callbackValue, resolve, reject) {
// 如果p和callbackValue相等,则说明产生了循环引用
if (p === callbackValue) {
return reject(new TypeError('靓仔,你的代码循环引用了'))
}
// 判断callbackValue是不是Promise类型
if (callbackValue instanceof MyPromise) {
callbackValue.then(value => resolve(value), resaon => reject(resaon))
} else {
resolve(callbackValue)
}
}
// 直接注册resolve方法,表示直接只返回一个成功的结果
static resolve(value) {
// 如果是promise对象则直接返回
if (value instanceof MyPromise) {
return value
} else {
// 如果不是promise对象,则重新创建一个
return new MyPromise((resolve) => {
resolve(value)
})
}
}
// 静态方法,返回错误的Promise
static reject(resaon) {
if (resaon instanceof MyPromise) {
return this.reject('[object Promise]')
} else {
// 如果不是promise对象,则重新创建一个
return new MyPromise((resolve, reject) => {
reject(resaon)
})
}
}
// all静态方法,有一个失败,直接返回失败,结果是按照传入的顺序返回
static all(promises) {
// 保存回调结果的数组
let result = [];
// 累加器,用来判断执行的方法队列是否执行完成
let count = 0;
// all 方法也返回一个promise对象
return new MyPromise((resolve, reject) => {
function pushResult(key, value) {
result[key] = value
count++
// 如果累加器和执行的任务列表长度相等,则说明已经完成了整个任务
if (count === promises.length) {
resolve(result)
}
}
// 循环处理要执行的任务
promises.forEach((task, index) => {
if (task instanceof MyPromise) {
task.then((v) => pushResult(index, v), (resaon) => reject(resaon))
} else {
pushResult(index, promises[index])
}
})
})
}
// 所有 Promises 都完成后(包含成功和失败)
static allSettled(promises) {
return new MyPromise((resolve) => {
let results = []
let count = 0
promises.forEach((task, index) => {
if (task instanceof MyPromise) {
task.finally(_ => {
count++
results[index] = {
status: task.status,
value: task.value || task.resaon
}
if (count === promises.length) {
resolve(results)
}
})
} else {
count++
results[index] = {
status: 'fulfilled',
value: task
}
if (count === promises.length) {
resolve(results)
}
}
})
})
}
// 有一个成功就返回
static any(promises) {
return new MyPromise((resolve) => {
promises.forEach((task) => {
if (task instanceof MyPromise) {
task.then(_ => {
resolve(task.value)
})
} else {
resolve(task)
}
})
})
}
// 有一个改变状态(成功或者失败)就返回
static race(promises) {
return new MyPromise((resolve) => {
promises.forEach((task) => {
if (task instanceof MyPromise) {
task.finally(_ => {
resolve(task.value || task.resaon)
})
} else {
resolve(task)
}
})
})
}
}
MyPromise.defer = MyPromise.deferred = function () {
let testObj = {}
testObj.promise = new Promise((resolve, reject) => {
testObj.resolve = resolve
testObj.reject = reject
})
return testObj
}
module.exports = MyPromise