-
Notifications
You must be signed in to change notification settings - Fork 0
/
10、手写promise.js
287 lines (269 loc) · 8.03 KB
/
10、手写promise.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
// 记录Promise的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
/**
* 运行一个微队列任务
* 把传递的函数放到微队列中
* @param {Function} callback
*/
function runMicroTask(callback) {
// 判断node环境
// 为了避免「变量未定义」的错误,这里最好加上前缀globalThis
// globalThis是一个关键字,指代全局对象,浏览器环境为window,node环境为global
if (globalThis.process && globalThis.process.nextTick) {
process.nextTick(callback);
} else if (globalThis.MutationObserver) {
const p = document.createElement('p');
const observer = new MutationObserver(callback);
observer.observe(p, {
childList: true, // 观察该元素内部的变化
});
p.innerHTML = '1';
} else {
setTimeout(callback, 0);
}
}
/**
* 判断一个数据是否是Promise对象
* @param {any} obj
* @returns
*/
function isPromise(obj) {
return !!(obj && typeof obj === 'object' && typeof obj.then === 'function');
}
class MyPromise {
/**
* 创建一个Promise
* @param {Function} executor 任务执行器,立即执行
*/
constructor(executor) {
this._state = PENDING; // 状态
this._value = undefined; // 数据
this._handlers = []; // 处理函数形成的队列
try {
executor(this._resolve.bind(this), this._reject.bind(this));
} catch (error) {
this._reject(error);
console.error(error);
}
}
/**
* 向处理队列中添加一个函数
* @param {Function} executor 添加的函数
* @param {String} state 该函数什么状态下执行
* @param {Function} resolve 让then函数返回的Promise成功
* @param {Function} reject 让then函数返回的Promise失败
*/
_pushHandler(executor, state, resolve, reject) {
this._handlers.push({
executor,
state,
resolve,
reject,
});
}
/**
* 根据实际情况,执行队列
*/
_runHandlers() {
if (this._state === PENDING) {
// 目前任务仍在挂起
return;
}
while (this._handlers[0]) {
const handler = this._handlers[0];
this._runOneHandler(handler);
this._handlers.shift();
}
}
/**
* 处理一个handler
* @param {Object} handler
*/
_runOneHandler({ executor, state, resolve, reject }) {
runMicroTask(() => {
if (this._state !== state) {
// 状态不一致,不处理
return;
}
if (typeof executor !== 'function') {
// 传递后续处理并非一个函数
this._state === FULFILLED ? resolve(this._value) : reject(this._value);
return;
}
try {
const result = executor(this._value);
if (isPromise(result)) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
console.error(error);
}
});
}
/**
* Promise A+规范的then
* @param {Function} onFulfilled
* @param {Function} onRejected
*/
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
this._pushHandler(onRejected, REJECTED, resolve, reject);
this._runHandlers(); // 执行队列
});
}
/**
* 仅处理失败的场景
* @param {Function} onRejected
*/
catch(onRejected) {
return this.then(null, onRejected);
}
/**
* 无论成功还是失败都会执行回调
* @param {Function} onSettled
*/
finally(onSettled) {
return this.then(
(data) => {
onSettled();
return data;
},
(reason) => {
onSettled();
throw reason;
}
);
}
/**
* 更改任务状态
* @param {String} newState 新状态
* @param {any} value 相关数据
*/
_changeState(newState, value) {
if (this._state !== PENDING) {
// 目前状态已经更改
return;
}
this._state = newState;
this._value = value;
this._runHandlers(); // 状态变化,执行队列
}
/**
* 标记当前任务完成
* @param {any} data 任务完成的相关数据
*/
_resolve(data) {
this._changeState(FULFILLED, data);
}
/**
* 标记当前任务失败
* @param {any} reason 任务失败的相关数据
*/
_reject(reason) {
this._changeState(REJECTED, reason);
}
/**
* 返回一个已完成的Promise
* 特殊情况:
* 1. 传递的data本身就是ES6的Promise对象
* 2. 传递的data是PromiseLike(Promise A+),返回新的Promise,状态和其保持一致即可
* @param {any} data
*/
static resolve(data) {
if (data instanceof MyPromise) {
return data;
}
return new MyPromise((resolve, reject) => {
if (isPromise(data)) {
data.then(resolve, reject);
} else {
resolve(data);
}
});
}
/**
* 得到一个被拒绝的Promise
* @param {any}} reason
*/
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
/**
* 得到一个新的Promise
* 该Promise的状态取决于proms的执行
* proms是一个迭代器,包含多个Promise
* 全部Promise成功,则返回的Promise成功,数据为所有Promise成功的数据,并且顺序是按照传入的顺序排列
* 只要有一个Promise失败,则返回的Promise失败,原因是第一个失败的Promise的原因
* @param {iterator} proms
*/
static all(proms) {
return new MyPromise((resolve, reject) => {
try {
const results = [];
let count = 0; // Promise的总数
let fulfilledCount = 0; // 已完成的数量
for (const p of proms) {
const i = count;
count++;
MyPromise.resolve(p).then((data) => {
fulfilledCount++;
results[i] = data;
if (fulfilledCount === proms.length) {
// 当前是最后一个Promise完成了
resolve(results);
}
}, reject);
}
if (count === 0) {
resolve([])
}
} catch (error) {
reject(error);
console.error(error);
}
});
}
/**
* 等待所有的Promise有结果之后
* 该方法返回的Promise完成
* 并且按照顺序将所有结果汇总
* @param {iterator} proms
*/
static allSettled(proms) {
const ps = [];
for (const p of proms) {
ps.push(
MyPromise.resolve(p).then(
(value) => ({
status: FULFILLED,
value,
}),
(reason) => ({
status: REJECTED,
reason,
})
)
);
}
return MyPromise.all(ps);
}
/**
* 返回的Promise与第一个有结果的一致
* @param {iterator} proms
*/
static race(proms) {
return new MyPromise((resolve, reject) => {
for (const p of proms) {
MyPromise.resolve(p).then(resolve, reject);
}
});
}
}