-
Notifications
You must be signed in to change notification settings - Fork 0
/
promise-source.js
225 lines (204 loc) · 6.4 KB
/
promise-source.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
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(promiseHandler) {
this.status = PENDING;
this.val = undefined;
this.resolveHandleList = [];
this.rejectHandleList = [];
try {
promiseHandler(this.triggerResolve, this.triggerReject);
} catch (error) {
this.triggerReject(error);
}
}
triggerResolve = (value) => {
setTimeout(() => {
// 如果调用resolve时已经不是pending了那就返回,因为状态不能逆转
if (this.status !== PENDING) {
return;
}
this.status = FULFILLED;
this.val = value;
this.resolveHandleList.forEach((handler) => {
handler(value);
});
this.resolveHandleList = [];
});
};
triggerReject = (error) => {
setTimeout(() => {
if (this.status !== PENDING) {
return;
}
debugger
this.status = REJECTED;
this.val = error;
this.rejectHandleList.forEach((handler) => {
handler(error);
});
this.rejectHandleList = [];
});
};
// then的意义就是注册后面的handle函数, 不是执行, 执行是发生在上一个promise完成之后,这里只是注册
// resolveHandler是不需要return值的
// 每个then接受两个参数,resolveHandler, rejectHandler
// then永远都要返回一个promise 这一点catch也一样
// resolveHandler, rejectHandler这两个方法return(或自然结束)或者throw error时。就是这个promise被resolve或reject的时机
then = (resolveHandler, rejectHandler) => {
const { status, val } = this;
return new MyPromise((onResolve, onReject) => {
// 这一步是为了融合当前then的下一个接着的then
// 因为当前的then会返回一个Promise,如果不调用这个onResolve,那么这个Promise就永远没法被resolve或者reject,也就不能被继续then
const unionResolveHandler = (value) => {
// 这里隐式得考虑了resolveHandler没有传的情况,这种情况相当于catch或者promise.then(null, null),如果promise的返回不是异常那么就会直接resolve掉
if (typeof resolveHandler !== "function") {
// 如果then的第一个参数不是function,那么就要忽略它,带着上一步的结果往下走
onResolve(value);
} else {
// 否则先执行当前then的resolveHandler,拿到结果传给下一个then的resolveHandler
const res = resolveHandler(value);
if (res instanceof MyPromise) {
res.then(onResolve, onReject);
} else {
onResolve(res);
}
}
};
const unionRejectHandler = (reason) => {
if (typeof rejectHandler !== "function") {
onReject(reason);
} else {
let res = null;
try {
res = rejectHandler(reason);
if (res instanceof MyPromise) {
res.then(onResolve, onReject);
} else {
onResolve(res);
}
} catch (error) {
console.log('catch ', error);
onReject(error);
}
}
};
switch (status) {
case PENDING: {
// 注册handler
this.resolveHandleList.push(unionResolveHandler);
this.rejectHandleList.push(unionRejectHandler);
break;
}
case FULFILLED: {
// 为什么这里会有fulfilled状态,是因为同一个promise可以被多次then,同理rejected
// 这种情况比较难模拟,第二次调then需要异步触发
// promise.then((v) => { console.log('resolve1', v )});
// setTimeout(() => {
// promise.then((v) => { console.log('resolve2', v )});
// }, 1000);
unionResolveHandler(val);
break;
}
case REJECTED: {
unionRejectHandler(val);
break;
}
}
});
};
catch = (nextRejectHandler) => {
return this.then(null, nextRejectHandler);
};
static resolve(value) {
if (value instanceof MyPromise) {
return value;
}
return new MyPromise((onResolve) => onResolve(value));
}
static reject(error) {
return new MyPromise((onResolve, onReject) => onReject(error));
}
static all(list) {
return new MyPromise((resolve, reject) => {
let count = 0;
const values = [];
for (const [i, myPromiseInstance] of list.entries()) {
MyPromise.resolve(myPromiseInstance).then(
(res) => {
values[i] = res;
count++;
if (count === list.length) resolve(values);
},
(err) => {
reject(err);
}
);
}
});
}
static race(list) {
return new MyPromise((resolve, reject) => {
list.forEach((item) => {
MyPromise.resolve(item).then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
}
);
});
});
}
finally(callback) {
return this.then(
value => MyPromise.resolve(callback()).then(() => value), // MyPromise.resolve执行回调,并在then中return结果传递给后面的Promise
reason => MyPromise.resolve(callback()).then(() => { throw reason }) // reject同理
)
}
}
// test case
// MyPromise.resolve('hello world').then(val => {
// console.log('resolve', val);
// })
// MyPromise.reject('hello world').catch(err => {
// console.log('reject', err);
// })
// MyPromise.reject("hello world")
// .catch((err) => {
// console.log("reject", err);
// return 12;
// }).then((val) => {
// console.log("resolve1", val);
// }).catch(() => {
// console.log(12993);
// }).finally(() => {
// console.log('finally');
// });
// const promise = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// console.log("promise resolved");
// resolve('kuimo');
// }, 1000);
// });
// promise
// .then((val) => {
// console.log("then", val);
// return "hello";
// })
// .then((v) => {
// console.log("resolve", v);
// })
// .catch((error) => {
// console.log("error", error);
// });
// promise.then((v) => { console.log('resolve1', v )});
// setTimeout(() => {
// promise.then((v) => { console.log('resolve2', v )});
// }, 1110);
MyPromise.resolve(123).catch((e) => { console.log('e', e); }).then((v) => {
console.log('value', v);
throw new Error('eee')
})