异步问题说明
howcode 2022-10-07 0 Promise
在上节代码中,如果我们执行的then
函数作以下修改
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111);
}, 1000);
});
p.then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
可以发现,此时控制台并没有输出任何结果,其主要原因就是then
函数比resolve
函数先执行了
添加打印
class Promise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
let resolve = (value) => {
console.log("resolve函数执行");
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
}
};
let reject = (reason) => {
if (this.state === "pending") {
this.state = "rejected";
this.reason = reason;
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
console.log("then函数执行");
if (this.state === "fulfilled") {
onFulfilled(this.value);
}
if (this.state === "rejected") {
onRejected(this.reason);
}
}
}
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111);
}, 2000);
});
p.then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);
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
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
可以发现控制台依次打印:
then函数执行
resolve函数执行
这是由于 js 执行的事件机制导致的,我们希望then
的回调,在promise
的状态更新为fulfilled
时才执行
试想一下,我们能不能提前将onFulfilled
和onRejected
存起来,等到resolve
后再去执行呢?
class Promise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onFulfilled = null;
this.onRejected = null;
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
this.onFulfilled(value);
}
};
let reject = (reason) => {
if (this.state === "pending") {
this.state = "rejected";
this.reason = reason;
this.onRejected(reason);
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
if (this.state === "fulfilled") {
onFulfilled(this.value);
}
if (this.state === "rejected") {
onRejected(this.reason);
}
if (this.state === "pending") {
this.onFulfilled = onFulfilled;
this.onRejected = onRejected;
}
}
}
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111);
}, 2000);
});
p.then((res) => {
console.log(res);
});
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
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
此时,果然在两秒后看到了打印结果!
然而,我们不妨多次执行试试:
p.then((res) => {
console.log(res);
});
p.then((res) => {
console.log(res);
});
1
2
3
4
5
6
7
2
3
4
5
6
7
你会发现,不管执行多少次.then
,都只会打印一次结果,简直离了个大谱
但只要想一下,就发现很容易想明白:不管你.then
多少次,只是改变了最终的onFulfilled
函数,而resolve
只是执行了一遍,那打印肯定只有一个
解决思路
在then
函数将onFulfilled
和onRejected
函数分别存入两个数组中,等到 resolve 的时候分别循环执行数组的方法
代码
class Promise {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
this.onResolvedCallbacks.forEach((fn) => fn());
}
};
let reject = (reason) => {
if (this.state === "pending") {
this.state = "rejected";
this.reason = reason;
this.onRejected(reason);
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
if (this.state === "fulfilled") {
onFulfilled(this.value);
}
if (this.state === "rejected") {
onRejected(this.reason);
}
if (this.state === "pending") {
// 将成功的时候要完成的事情存起来
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value);
});
// 将失败的时候要完成的事情存起来
this.onRejectedCallbacks.push(() => {
onRejected(this.value);
});
}
}
}
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111);
}, 2000);
});
p.then((res) => {
console.log(res, "1111");
});
p.then((res) => {
console.log(res, "2222");
});
p.then((res) => {
console.log(res, "3333");
});
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
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
评论
- 表情
——暂无评论——