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
|
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class WPromise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.callbacks = [];
try {
executor(this._resolve.bind(this), this._reject.bind(this));
} catch (e) {
this._reject(e);
}
}
_resolve(value) {
if (value instanceof WPromise) {
value.then(this._resolve.bind(this), this._reject.bind(this));
return;
}
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.callbacks.forEach((cb) => {
this._handle(cb);
});
}
}
static resolve(value) {
// 判断是否是thenable对象
if (
value instanceof WPromise ||
(typeof value === "object" && "then" in value)
) {
return value;
}
return new WPromise((resolve) => resolve(value));
}
_reject(reason) {
if (reason instanceof WPromise) {
reason.then(this._resolve.bind(this), this._reject.bind(this));
return;
}
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.callbacks.forEach((cb) => {
this._handle(cb);
});
}
}
_handle(cb) {
const { onFailed, onFulfilled, nextReject, nextResolve } = cb;
if (this.status === PENDING) {
this.callbacks.push(cb);
return;
}
if (this.status === FULFILLED) {
const nextValue =
typeof onFulfilled === "function"
? onFulfilled(this.value)
: this.value;
nextResolve(nextValue);
return;
}
if (this.status === REJECTED) {
const nextReason =
typeof onFailed === "function" ? onFailed(this.reason) : this.reason;
nextReject(nextReason);
}
}
then(onFulfilled, onFailed) {
// 值穿透
return new WPromise((nextResolve, nextReject) => {
this._handle({
nextReject,
nextResolve,
onFailed,
onFulfilled,
});
});
}
static all(arr) {
return new WPromise((resolve, reject) => {
const resultArr = [];
let len = 0;
Array.from(arr).forEach((item, idx) => {
WPromise.resolve(item).then((data) => {
resultArr[idx] = data;
len++;
if (len === arr.length) {
resolve(resultArr);
}
}, reject);
});
});
}
static race(arr) {
return new WPromise((resolve, reject) => {
Array.from(arr).forEach((item) => {
WPromise.resolve(item).then(resolve, reject);
});
});
}
}
|