# Promise
# Promise 一些特性
图解 Promise 实现原理 (opens new window)
在 fetchData 异步函数运行完之前,回调函数式不会被调用的,即使异步函数完成或失败,在这之后通过 then() 添加的回调函数,还是会被调用,通过多次调用 then() 可以添加多个回调函数,它们会按插入循序执行,如果 then 中的回调函数没有返回值,则下一个 then 的回调中将接收不到值,第一个 catch 捕捉到错误之后,还是会继续执行下面的代码,直到链式调用结束为止,且 catch 只会捕捉其前面回调中的报错
# 手写实现 Promise
Promise 的 then 方法实际是用来注册回调方法的,实际调用还是在 resolve 中执行的, 并且 then 方法会返回一个新的 Promise 对象,
class MyPromise {
callbacks = [];
value = null;
state = "pending";
constructor(fn) {
fn(this._resolve.bind(this), this._reject.bind(this));
}
// 有时候 then 方法回调中可能会返回一个 promise
// 而根据 Promise/A+ 规范定义的 promise 是一个拥有 then 方法的对象或函数
_resolve(value) {
if (value && (typeof value === "object" || typeof value === "function")) {
const then = value.then;
if (typeof then === "function") {
// 此处的 value 是 then方法调用时的环境,因为 then 方法属于 value
then.call(value, this._resolve.bind(this), this._reject.bind(this));
return;
}
}
this.state = "fulfilled";
this.value = value;
this.callbacks.forEach((cb) => this._handle(cb));
}
_reject(err) {
this.state = "rejected";
this.value = err;
this.callbacks.forEach((cb) => this._handle(cb));
}
_handle(cb) {
// 等待态
if (this.state === "pending") {
this.callbacks.push(cb);
return;
}
// 执行态
if (this.state === "fulfilled") {
if (!cb.onFulfilled) {
cb.resolve(this.value);
return;
}
try {
const ret = cb.onFulfilled(this.value);
cb.resolve(ret);
} catch (e) {
cb.reject(e);
}
return;
}
// 拒绝态
if (this.state === "rejected") {
if (!cb.onRejected) {
cb.reject(this.value);
return;
}
try {
// catch 捕获到错误之后,如果后面还有then方法,则应该执行 resolve
const ret = cb.onRejected(this.value);
cb.resolve(ret);
} catch (e) {
cb.reject(e);
}
return;
}
}
// ① 当参数是一个 promise 对象时,直接返回这个 promise
// ② 如果参数是其他类型的值,则返回一个新的 promise 包装下这个参数
// ③ 如果 value 为 null,直接返回一个新的 promise
// ④ value 是一个 thenable 的对象: 定义了 then 方法的对象或函数
static resolve(value) {
if (!value) return new MyPromise((resolve) => resolve());
if (value instanceof MyPromise) return value;
if (typeof value === "object" && typeof value.then === "function") {
return new MyPromise((resolve) => value.then(resolve));
}
return new MyPromise((resolve) => resolve(value));
}
// Promise.reject 始终返回一个 拒绝态 的 Promise 的实例
static reject(value) {
if (!value) return new MyPromise((resolve, reject) => reject());
if (typeof value === "object" && typeof value.then === "function") {
return new MyPromise((resolve, reject) => value.then(reject));
}
return new MyPromise((resolve, reject) => reject(value));
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this._handle({
onFulfilled: onFulfilled,
onRejected: onRejected,
resolve: resolve,
reject: reject,
});
});
}
catch(onError) {
return this.then(null, onError);
}
finally(onDone) {}
}
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
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
# 手动实现 Promise.retry 方法
Promise.retry = function (fn , count) {
return new Promise( async (resolve, reject) => {
while (count > 0) {
try {
const res = await fn();
resolve(res);
return;
} catch () {
if(count) reject();
count--;
}
}
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14