-
Notifications
You must be signed in to change notification settings - Fork 7
/
myPromiseFully.js
386 lines (360 loc) · 14.3 KB
/
myPromiseFully.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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/**
* 在 myPromise.js 基础上,根据规范实现了 Promise 的全部方法:
* - Promise.resolve()
* - Promise.reject()
* - Promise.prototype.catch()
* - Promise.prototype.finally()
* - Promise.all()
* - Promise.allSettled()
* - Promise.any()
* - Promise.race()
*/
class myPromise {
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
constructor(func) {
this.PromiseState = myPromise.PENDING;
this.PromiseResult = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
try {
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error)
}
}
resolve(result) {
if (this.PromiseState === myPromise.PENDING) {
this.PromiseState = myPromise.FULFILLED;
this.PromiseResult = result;
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(reason) {
if (this.PromiseState === myPromise.PENDING) {
this.PromiseState = myPromise.REJECTED;
this.PromiseResult = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
}
}
/**
* [注册fulfilled状态/rejected状态对应的回调函数]
* @param {function} onFulfilled fulfilled状态时 执行的函数
* @param {function} onRejected rejected状态时 执行的函数
* @returns {function} newPromsie 返回一个新的promise对象
*/
then(onFulfilled, onRejected) {
let promise2 = new myPromise((resolve, reject) => {
if (this.PromiseState === myPromise.FULFILLED) {
setTimeout(() => {
try {
if (typeof onFulfilled !== 'function') {
resolve(this.PromiseResult);
} else {
let x = onFulfilled(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
reject(e);
}
});
} else if (this.PromiseState === myPromise.REJECTED) {
setTimeout(() => {
try {
if (typeof onRejected !== 'function') {
reject(this.PromiseResult);
} else {
let x = onRejected(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
reject(e)
}
});
} else if (this.PromiseState === myPromise.PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
if (typeof onFulfilled !== 'function') {
resolve(this.PromiseResult);
} else {
let x = onFulfilled(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
if (typeof onRejected !== 'function') {
reject(this.PromiseResult);
} else {
let x = onRejected(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
reject(e);
}
});
});
}
})
return promise2
}
/**
* Promise.resolve()
* @param {[type]} value 要解析为 Promise 对象的值
*/
static resolve(value) {
// 如果这个值是一个 promise ,那么将返回这个 promise
if (value instanceof myPromise) {
return value;
} else if (value instanceof Object && 'then' in value) {
// 如果这个值是thenable(即带有`"then" `方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;
return new myPromise((resolve, reject) => {
value.then(resolve, reject);
})
}
// 否则返回的promise将以此值完成,即以此值执行`resolve()`方法 (状态为fulfilled)
return new myPromise((resolve) => {
resolve(value)
})
}
/**
* Promise.reject()
* @param {*} reason 表示Promise被拒绝的原因
* @returns
*/
static reject(reason) {
return new myPromise((resolve, reject) => {
reject(reason);
})
}
/**
* Promise.prototype.catch()
* @param {*} onRejected
* @returns
*/
catch (onRejected) {
return this.then(undefined, onRejected)
}
/**
* Promise.prototype.finally()
* @param {*} callBack 无论结果是fulfilled或者是rejected,都会执行的回调函数
* @returns
*/
finally(callBack) {
return this.then(callBack, callBack)
}
/**
* Promise.all()
* @param {iterable} promises 一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入
* @returns
*/
static all(promises) {
return new myPromise((resolve, reject) => {
// 参数校验
if (Array.isArray(promises)) {
let result = []; // 存储结果
let count = 0; // 计数器
// 如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise
if (promises.length === 0) {
return resolve(promises);
}
promises.forEach((item, index) => {
// myPromise.resolve方法中已经判断了参数是否为promise与thenable对象,所以无需在该方法中再次判断
myPromise.resolve(item).then(
value => {
count++;
// 每个promise执行的结果存储在result中
result[index] = value;
// Promise.all 等待所有都完成(或第一个失败)
count === promises.length && resolve(result);
},
reason => {
/**
* 如果传入的 promise 中有一个失败(rejected),
* Promise.all 异步地将失败的那个结果给失败状态的回调函数,而不管其它 promise 是否完成
*/
reject(reason);
}
)
})
} else {
return reject(new TypeError('Argument is not iterable'))
}
})
}
/**
* Promise.allSettled()
* @param {iterable} promises 一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入
* @returns
*/
static allSettled(promises) {
return new myPromise((resolve, reject) => {
// 参数校验
if (Array.isArray(promises)) {
let result = []; // 存储结果
let count = 0; // 计数器
// 如果传入的是一个空数组,那么就直接返回一个resolved的空数组promise对象
if (promises.length === 0) return resolve(promises);
promises.forEach((item, index) => {
// 非promise值,通过Promise.resolve转换为promise进行统一处理
myPromise.resolve(item).then(
value => {
count++;
// 对于每个结果对象,都有一个 status 字符串。如果它的值为 fulfilled,则结果对象上存在一个 value 。
result[index] = {
status: 'fulfilled',
value
}
// 所有给定的promise都已经fulfilled或rejected后,返回这个promise
count === promises.length && resolve(result);
},
reason => {
count++;
/**
* 对于每个结果对象,都有一个 status 字符串。如果值为 rejected,则存在一个 reason 。
* value(或 reason )反映了每个 promise 决议(或拒绝)的值。
*/
result[index] = {
status: 'rejected',
reason
}
// 所有给定的promise都已经fulfilled或rejected后,返回这个promise
count === promises.length && resolve(result);
}
)
})
} else {
return reject(new TypeError('Argument is not iterable'))
}
})
}
/**
* Promise.any()
* @param {iterable} promises 一个promise的iterable类型(注:Array,Map,Set都属于ES6的iterable类型)的输入
* @returns
*/
static any(promises) {
return new myPromise((resolve, reject) => {
// 参数校验
if (Array.isArray(promises)) {
let errors = []; //
let count = 0; // 计数器
// 如果传入的参数是一个空的可迭代对象,则返回一个 已失败(already rejected) 状态的 Promise。
if (promises.length === 0) return reject(new AggregateError([], 'All promises were rejected'));
promises.forEach(item => {
// 非Promise值,通过Promise.resolve转换为Promise
myPromise.resolve(item).then(
value => {
// 只要其中的一个 promise 成功,就返回那个已经成功的 promise
resolve(value);
},
reason => {
count++;
errors.push(reason);
/**
* 如果可迭代对象中没有一个 promise 成功,就返回一个失败的 promise 和AggregateError类型的实例,
* AggregateError是 Error 的一个子类,用于把单一的错误集合在一起。
*/
count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'));
}
)
})
} else {
return reject(new TypeError('Argument is not iterable'))
}
})
}
/**
* Promise.race()
* @param {iterable} promises 可迭代对象,类似Array。详见 iterable。
* @returns
*/
static race(promises) {
return new myPromise((resolve, reject) => {
// 参数校验
if (Array.isArray(promises)) {
// 如果传入的迭代promises是空的,则返回的 promise 将永远等待。
if (promises.length > 0) {
promises.forEach(item => {
/**
* 如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,
* 则 Promise.race 将解析为迭代中找到的第一个值。
*/
myPromise.resolve(item).then(resolve, reject);
})
}
} else {
return reject(new TypeError('Argument is not iterable'))
}
})
}
}
/**
* 对resolve()、reject() 进行改造增强 针对resolve()和reject()中不同值情况 进行处理
* @param {promise} promise2 promise1.then方法返回的新的promise对象
* @param {[type]} x promise1中onFulfilled或onRejected的返回值
* @param {[type]} resolve promise2的resolve方法
* @param {[type]} reject promise2的reject方法
*/
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
throw new TypeError('Chaining cycle detected for promise');
}
if (x instanceof myPromise) {
x.then(y => {
resolvePromise(promise2, y, resolve, reject)
}, reject);
} else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
try {
var then = x.then;
} catch (e) {
return reject(e);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (called) return;
called = true;
reject(r);
}
)
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
} else {
return resolve(x);
}
}
myPromise.deferred = function () {
let result = {};
result.promise = new myPromise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
module.exports = myPromise;