手写Promise
# 分析
Promise 的创建过程是new
出来的,所以 Promise 是个类
class Promise {}
const p = new Promise();
2
3
在创建过程中,需要传入一个函数,并且在两个函数是立即执行的
const p = new Promise((resolve, reject) => {});
故我们需要在 Promise 接收该函数
class Promose {
constructor(executor) {
executor();
}
}
2
3
4
5
此时可以打印一下内容
const p = new Promise((resolve, reject) => {
console.log("立即执行"); //立即执行
console.log(resolve, reject); // undefined undefined
});
2
3
4
如果在executor
函数传入某些数据,例如executor(1,2)
const p = new Promise((resolve, reject) => {
console.log("立即执行"); //立即执行
console.log(resolve, reject); // 1 2
});
2
3
4
因此我们得知,resolve
和reject
是Promise
内部中实现的函数
# 创建 resolve 与 reject
class Promose {
constructor(executor) {
let resolve = () => {
console.log("将状态转改为成功,记录成功的信息");
};
let reject = () => {
console.log("将状态转改为失败,记录失败的信息");
};
executor(resolve, reject);
}
}
2
3
4
5
6
7
8
9
10
11
const p = new Promise((resolve, reject) => {
console.log("立即执行"); //立即执行
resolve(); // 将状态转改为成功,记录成功的信息
});
2
3
4
目前只是描述了函数的功能,但实际上的状态改变是怎么实现的呢?
# 处理三个状态
class Promose {
constructor(executor) {
this.state = "pending";
let resolve = () => {
this.state = "fulfilled";
};
let reject = () => {
this.state = "rejected";
};
executor(resolve, reject);
}
}
2
3
4
5
6
7
8
9
10
11
12
思考
除了相应的状态改变后,还应该有记录相应的成功与失败信息,以便后期在执行then
或者catch
函数时取到相应的信息
class Promose {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reson = undefined;
let resolve = (value) => {
this.state = "fulfilled";
this.value = value;
};
let reject = (reson) => {
this.state = "rejected";
this.reson = reson;
};
executor(resolve, reject);
}
}
const p = new Promise((resolve, reject) => {
resolve("成功啦");
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
到这之后,基本的状态改变就实现了,然而事情并没有结束,我们在前面提到过,Promise
的状态改变是凝固的
const p = new Promise((resolve, reject) => {
resolve("成功啦");
reject("失败啦");
});
2
3
4
可以发现,此时的状态可以发生多次改变,因此我们需要限制,只有状态为pending
时才可以发生改变
class Promose {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reson = undefined;
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
}
};
let reject = (reson) => {
if (this.state === "pending") {
this.state = "rejected";
this.reson = reson;
}
};
executor(resolve, reject);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# then
大家思考下,then 方法是在类的实例上加,还是在原型上添加?答案是:原型上。因为每个 Promise 都需要 then 方法
Promise 细节:
p.then()
时,里面是可以接收两个函数的,一个是onFulfilled
,另一个是onRejected
,这时有些同志看了不免有两点疑惑,第一点疑惑是:then 居然能接收两个函数?;第二个疑惑是:then 如果能接收到onRejected
,那为什么还需要catch
?
then
确实能接收到两个函数,但我们平时基本只会用到第一个onFulfilled
;第二个onRejected
和catch
的区别是:onRejected
只能处理发生在p
的错误,而catch
除了能处理p
的错误,还能处理onFulfilled
内部的错误以及p.then().then()....
中每一环的错误,所以我们更习惯用catch
代码:
class Promose {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reson = undefined;
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
}
};
let reject = (reson) => {
if (this.state === "pending") {
this.state = "rejected";
this.reson = reson;
}
};
executor(resolve, reject);
}
then(onFulfilled, onRejected) {
// 成功执行onFulfilled
if (this.state === "fulfilled") {
onFulfilled();
}
// 失败执行onRejected
if (this.state === "rejected") {
onRejected();
}
}
}
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
然而此时执行:
const p = new Promise((resolve, reject) => {
resolve("成功啦");
});
p.then((res) => {
console.log(res); // undefined
});
2
3
4
5
6
这是因为res
外部并没有传过来
优化代码:
class Promose {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reson = undefined;
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
}
};
let reject = (reson) => {
if (this.state === "pending") {
this.state = "rejected";
this.reson = reson;
}
};
executor(resolve, reject);
}
then(onFulfilled, onRejected) {
// 成功执行onFulfilled
if (this.state === "fulfilled") {
onFulfilled(this.value);
}
// 失败执行onRejected
if (this.state === "rejected") {
onRejected(this.reason);
}
}
}
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
# 小优化
在执行executor
时,也有可能代码报错,此时也应该进行reject
class Promose {
constructor(executor) {
this.state = "pending";
this.value = undefined;
this.reson = undefined;
let resolve = (value) => {
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
}
};
let reject = (reson) => {
if (this.state === "pending") {
this.state = "rejected";
this.reson = reson;
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// 成功执行onFulfilled
if (this.state === "fulfilled") {
onFulfilled(this.value);
}
// 失败执行onRejected
if (this.state === "rejected") {
onRejected(this.reason);
}
}
}
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
评论
- 表情