手写Promise

手写Promise

😆

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
class TPromise {
static PENDING = 'PENDING';
static RESOLVED = 'RESOLVED';
static REJECTED = 'REJECTED';

constructor(handler) {
// 下面队列用于存储方法
this.resolveQueues = [];
this.rejectQueues = [];
this.finallyQueues = [];
this.state = TPromise.PENDING;
handler(this._resolve.bind(this), this._reject.bind(this));
}

_resolve(val) {
// 因为promise是微任务,这里使用MutationObserver来模拟微任务
let observer = new MutationObserver(() => {
// 一旦状态机修改过状态,那么就无法再改变状态
if (this.state !== TPromise.PENDING) return;
this.state = TPromise.RESOLVED;
this.value = val;
let handler;
while ((handler = this.resolveQueues.shift())) {
handler(this.value);
}
while ((handler = this.finallyQueues.shift())) {
handler();
}
});

observer.observe(document.body, {
attributes: true
});
document.body.setAttribute('_promise', Date.now());
}

_reject(val) {
// 因为promise是微任务,这里使用MutationObserver来模拟微任务
let observer = new MutationObserver(() => {
// 一旦状态机修改过状态,那么就无法再改变状态
if (this.state !== TPromise.PENDING) return;
this.state = TPromise.REJECTED;
this.value = val;
let handler;
while ((handler = this.rejectQueues.shift())) {
handler(this.value);
}
while ((handler = this.finallyQueues.shift())) {
handler();
}
});

observer.observe(document.body, {
attributes: true
});
document.body.setAttribute('_promise', Date.now());
}

then(resolveHandler, rejectHandler) {
// 每一个then都是返回一个新的promise
return new TPromise((resolve, reject) => {
if (typeof resolveHandler === 'function') {
const newResolveHandler = val => {
let result = resolveHandler(val);
if (result instanceof TPromise) {
// 如果返回的结果是个promise实例的话,调用下面方法
result.then(resolve, reject);
} else {
resolve(result);
}
};
// promise每次resolve的时候,都会去执行resolveQueues队列中的所有方法
this.resolveQueues.push(newResolveHandler);
} else {
// promise每次resolve的时候,都会去执行resolveQueues队列中的所有方法
this.resolveQueues.push(resolve);
}

if (typeof rejectHandler === 'function') {
const newRejectHandler = val => {
let result = rejectHandler(val);
if (result instanceof TPromise) {
result.then(resolve, reject);
} else {
resolve(result);
}
};
this.rejectQueues.push(newRejectHandler);
} else {
this.rejectQueues.push(reject);
}
});
}

catch(rejectHandler) {
// catch 实质上是then的一种简写
return this.then(undefined, rejectHandler);
}

finally(finallyHandler) {
return new TPromise((resolve, reject) => {
if (typeof finallyHandler === 'function') {
const newFinallyHandler = () => {
const result = finallyHandler();
if (result instanceof TPromise) {
result.finally(() => {
if (this.state === TPromise.RESOLVED) resolve(this.value);
else if (this.state === TPromise.REJECTED) reject(this.value);
});
} else {
if (this.state === TPromise.RESOLVED) resolve(this.value);
else if (this.state === TPromise.REJECTED) reject(this.value);
}
};
this.finallyQueues.push(newFinallyHandler);
}
});
}

// all 只有当所有promise都成功返回时,才resolve
static all(arr) {
let i = 0;
const resArr = [];
return new TPromise((resolve, reject) => {
arr.forEach((it, index) => {
it.then(res => {
i++;
resArr[index] = res;
if (i >= arr.length) {
resolve(resArr);
}
}).catch(err => {
reject(err);
});
});
});
}

// race 返回第一个有结果的promise
static race(arr) {
return new TPromise((resolve, reject) => {
arr.forEach((it, index) => {
it.then(res => {
resolve(res);
}).catch(err => {
reject(err);
});
});
});
}

static resolve(val) {
return new TPromise((resolve, reject) => {
if (val instanceof TPromise) {
val.then(resolve, reject);
} else {
resolve(val);
}
});
}

// 注意reject 会原封不动的将参数返回
static reject(val) {
return new TPromise((resolve, reject) => {
reject(val);
});
}
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×