丁老师学习名言 你用你会的知识去解释他, => 解释通了, 你就明白了 => 解释不通, 该学习了!!
继续..
step1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
constructor () {
...
用来存放then中的回调
this.resoveCB = null;
this.rejectCB = null;
}
...
then (resolveFn,rejectFn) {
...
if (this.state == "pending") {
return new myPromise((resolve, reject) => {
this.resolveCB = ((resolveFn)=>{
return () => {
var res = resolveFn(this.data);
}
})(resolveFn);
})
}
}
从这里开始就烧脑了,,, 首先我们需要在 ‘pending’ 时先返回一个对象, 我们需要在 this.resolveCB中存一下函数resolveFn 但我们还需要把相应的参数也放进去 所以套了一层 函数绑定参数.
step2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (this.state == "pending") {
return new myPromise((resolve, reject) => {
this.resolveCB = ((resolveFn)=>{
return () => {
var res = resolveFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(resolveFn);
})
}
刚开始确实是没看懂, 跟着执行顺序捋了一遍, 为什么这个逻辑成立是理解了. 因为pending 所以我们用this.resolveCB 来存了一下 函数, 返回了一个新的中间promise对象, 当前一个promise对象有了状态的变化时, 这个对象也要跟着改变对象, 如果有new了一个新的 new Promise对象, 就需要在这个new Promise对象的 状态改变时, 把中间的promise状态改变, 这样才能触发 保存的函数? 这里回头再思考
step3 补齐一下rejiect 这边
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
if (this.state == "pending") {
return new myPromise((resolve, reject) => {
this.resolveCB = ((resolveFn)=>{
return () => {
var res = resolveFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(resolveFn);
this.rejectCB = ((rejectFn)=>{
return () => {
var res = rejectFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(rejectFn);
})
}
有一个地方我有点懵逼, 或者之前我理解有错误. 我以为promise 的后序then中 只要有一次进入 resolve 之后的都会进入resolve 有一次进入 reject 之后的都会进入rejiect 但老师写的reject 里 向下传递的状态是 resolve 也就是说 reject 线路还会回到 resolve?
测试 ``` let P = new Promise((res,rej) => {
rej(123) }).then(null,(data) => { console.log(data); return 223 }).then(null,(data) => { console.log(data); })// 按我之前的理解, 应该是返回223 但没有
let P = new Promise((res,rej) => {
rej(123) }).then(null,(data) => { console.log(data); return 223 }).then((data) => { console.log(data); })// 返回了223
1
2
3
4
5
6
> 这要怎么理解呢?
> 也就是说默认then 执行过后返回的promise对象的状态都是 resolved
> 除非回调中返回的是新的 promise 对象.
step4
为了一下这种情况
let p = new myPromise((res,rej) => { rej(123) })
p.then(null,(data) => {console.log(data + 200)}); p.then(null,(data) => {console.log(data)});
1
constructor(){ …
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
this.resolveCB = [];
this.rejectCB = [];
let resolve = (data) => {
if (this.state == "pending") {
this.state = "resolved"
this.data = data;
this.resolveCB.forEach(fn => fn());
}
}
let reject = (data) => {
if (this.state == "pending") {
this.state = "rejected"
this.data = data;
this.rejectCB.forEach(fn => fn());
}
} } ... then(resolveFn,rejectFn){ ...
if (this.state == "pending") {
return new myPromise((resolve, reject) => {
this.resolveCB.push((resolveFn)=>{
return () => {
var res = resolveFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(resolveFn);
this.rejectCB.push((rejectFn)=>{
return () => {
var res = rejectFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(rejectFn);
})
} }
1
2
step5
让所有同步操作都变成异步?
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
let resolve = (data) => {
if (this.state == "pending") {
setTimeout(() => {
this.state = "resolved"
this.data = data;
this.resolveCB.forEach(fn => fn());
},0)
}
}
let reject = (data) => {
if (this.state == "pending") {
setTimeout(() => {
this.state = "rejected"
this.data = data;
this.rejectCB.forEach(fn => fn());
},0)
}
} ``` 贴一下完整版 ``` class myPromise {
constructor (fn) {
if (typeof fn !== "function") {
throw TypeError(`myPromise resolver ${fn} is not a function`)
}
this.state = "pending";
this.data = undefined;
this.resolveCB = [];
this.rejectCB = [];
let resolve = (data) => {
if (this.state == "pending") {
setTimeout(() => {
this.state = "resolved"
this.data = data;
this.resolveCB.forEach(fn => fn());
},0)
}
}
let reject = (data) => {
if (this.state == "pending") {
setTimeout(() => {
this.state = "rejected"
this.data = data;
this.rejectCB.forEach(fn => fn());
},0)
}
}
fn(resolve,reject);
}
then (resolveFn, rejectFn) {
if (this.state == "resolved") {
let rus = resolveFn(this.data);
if (rus instanceof myPromise) {
return rus
}else{
return myPromise.resolve(rus);
}
}
if (this.state == "rejected") {
let rus = rejectFn(this.data);
if (rus instanceof myPromise) {
return rus
}else{
return myPromise.resolve(rus);
}
}
if (this.state == "pending") {
return new myPromise((resolve, reject) => {
console.log(this.resolveCB);
this.resolveCB.push(((resolveFn)=>{
return () => {
var res = resolveFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(resolveFn));
this.rejectCB.push(((rejectFn)=>{
return () => {
var res = rejectFn(this.data);
if (res instanceof myPromise) {
res.then(resolve,reject);
} else{
resolve(res)
}
}
})(rejectFn));
})
}
}
static resolve (data) {
return new myPromise((suc) => {
suc(data);
})
}
static reject (data) {
return new myPromise((suc,err) => {
err(data);
})
}
} ```
思考 实际上到昨天的同步处理为止,都是比较简单的. 到了要解决异步问题的时候, 我们发现必须要先返回一个对象, 并且要把函数先保存下来. 问题还在于, 我们要进行链式调用, 在明确每次then返回的对象都不相同时, 我们要解决一个问题就是,对象间的传递. 传递状态, 传递数据, 传递函数? 昨天我写得异常暴力版本,主要就是想不通怎么传递, 因为传递状态和数据的接口已经写好了, 理论上就应该用这两个接口 但这两个接口貌似只能在 new 新对象的时候才能传.
我们看一下就会发现, 丁老师的版本是怎么传的呢? 他确实是先返回了一个对象, 也是存了函数, 最核心的就是开篇讲的, 他在存函数的时候, 用函数的多层嵌套的方式, 把数据和函数一起绑定之后的函数放进了数组里. 然后在这个函数中调用各个接口,完成三个对象之间的状态,数据的传递. 当然我觉得我还是很难想到,但比刚开始好多了.
这应该是最近看到的代码中最漂亮的代码了.