PromiseA-用例

前言

一直听说想成为一名高级前端程序员需要理解一些源码,那就从 Promise 开始吧,作者尽量用最少的语言让你理解 Promise

准备

安装 Promise 测试工具#

1
npm i promises-aplus-tests -g

运行测试工具,检测 Promise 是否符合规范

1
promises-aplus-tests [promise文件名]

完整代码先过用例

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
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
this.reject(e);
}
}
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== "function") {
onFulfilled = (value) => value;
}
if (typeof onRejected !== "function") {
onRejected = (err) => {
throw err;
};
}
let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
});
return promise2;
}
}

const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x)
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);

if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called;
try {
const then = x.then;
if (typeof then !== "function") resolve(x);
else {
then.call(
x,
(value) => {
if (called) return;
called = true;

resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
}
);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
};

Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;

完整代码 127 行,增加 Promise 测试代码一共 136 行代码。

如何测试

在 VS Code 新建文件 promise.jspromise.jspromise.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// promise代码
class Promise {
constructor() {}
then() {}
catch() {}
}

// 测试代码
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = Promise;

在 promise.jspromise.jspromise.js 文件所在目录打开终端,输入下面命令即可测试 Promise 是否符合规范

1
promises-aplus-tests promise.js

声明 Promise 类

Promise 常用的有 then 方法 和 catch,先用 ES6 语法声明一个 Promise 类

这点不难理解吧?

1
2
3
4
5
class Promise {
constructor() {}
then() {}
catch() {}
}

constructor

正常使用 Promise 一般 如下图所示, new Promise(参数是一个函数)

1
2
3
4
5
let p1 = new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 1000);
});

所以 在 Promise 类的 constructor 使用 executor 形参接收这个参数,这点不难理解吧?

1
2
3
4
5
class Promise {
constructor(executor) {}
then() {}
catch() {}
}

executor 是用户输入的参数,咱们不能相信用户一定会使用一个函数作为 new Promise(参数) 对不对?

所以这里就需要判断一下 executor 是否是一个函数。

很好理解吧?

1
2
3
4
5
6
7
8
9
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
}
then() {}
catch() {}
}

executor

constructor 这节已经知道 executor 是个函数了,executor 函数也是有参数的呀。

如下 Promise 使用代码

1
2
3
4
5
6
7
8
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random() > 0.5 ? resolve("正确") : reject("错误");
}, 1000);
});
p1.then((value) => {
console.log(value);
});

romises/A+ 规范中说:resolve 是进行成功的一系列操作,reject 是失败的一些操作,还有成功原因,失败原因?这些咱们的 Promise 都要有,都加上

resolve 和 reject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}

// promise 被解决时传递给解决回调的值
this.value = null;

// promise 被拒绝时传递给解决回调的值
this.reason = null;

// 成功的一系列操作
const resolve = () => {};

//失败的一些操作
const reject = () => {};
executor(resolve, reject);
}
then() {}
catch() {}
}

状态

Promises/A+译文

Promises/A+ 规范中说,Promise 要有 3 种状态。咱们在代码中将这三种状态加上,这很好理解吧

常量命名用大写,这点可以理解的

PENDING 、FULFILLED 和 REJECTED

1
2
3
4
5
6
7
8
9
10
11
12
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
}
then() {}
catch() {}
}

要求说,Pending 状态只能去 Fulfilled 或者 Rejected 且不可变,这就需要一个变量记录 Promise 状态值, 并且状态值初始值为 Pending 这点可以理解吧

this.state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = () => {};
const reject = () => {};
executor(resolve, reject);
}
then() {}
catch() {}
}

Pending 状态只能去 Fulfilled 或者 Rejected 意味着 resolve 和 reject 只有在 Pending 可以执行,没问题吧。

所以需要在 resolve 和 reject 函数中加判断

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
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = () => {
// PENDING状态才能执行,执行完成修改状态为FULFILLED
if (this.state === PENDING) {
this.state = FULFILLED;
}
};
const reject = () => {
// PENDING状态才能执行,执行完成修改状态为 REJECTED
if (this.state === PENDING) {
this.state = REJECTED;
}
};
executor(resolve, reject);
}
then() {}
catch() {}
}

执行完成功或者异常函数是不是要有成功或者异常数据呀,这些回调的值是不是需要保存到类中,在 then 方法中返回?

添加上

value 和 reason

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
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;

// 解决时传递给解决回调的值
this.value = value;
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;

// 拒绝时传递给解决回调的值
this.reason = reason;
}
};
executor(resolve, reject);
}
then() {}
catch() {}
}

constructor 这就完成了吗?不,还差一步。

executor 是个函数,这在上文中有描述,但是函数有没有可能执行错误,直接执行这个函数报错,报错怎么处理?try/catch 大法喽

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
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;

// 解决时传递给解决回调的值
this.value = value;
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;

// 拒绝时传递给解决回调的值
this.reason = reason;
}
};
try {
// 如果函数顺利执行,执行函数
executor(resolve, reject);
} catch (error) {
// 函数抛出异常,将异常信息通过 reject 返回
reject(error);
}
}
then() {}
catch() {}
}

Then

单独写 then 这个函数,暂时忽略 constructor 代码吧。代码太多容易混淆。读者觉得呢?

1
then() {}

Promises/A+译文

根据规范中规定 then 要有两个参数,并且这两个参数需要是函数,如果不是函数需要忽略

所以 then 代码如下;不难理解吧

1
2
3
4
5
6
7
8
9
10
then(onFulfilled, onRejected){
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}
}

onFulfilled 和 onRejected

接着看规范描述

onFulfilled 和 onRejected 调用次数不可超过一次,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}

// 只执行一次
if (this.state === Promise.FULFILLED) {
onFulfilled(this.value);
}

if (this.state === Promise.REJECTED) {
onRejected(this.reason);
}
}

resolve 支持异步

这样就可以了吗??不不不

如果 Promise 中 resolve 是在异步函数中执行的,目前我写的 Promise 代码中 console 并不会执行。

1
2
3
4
5
6
7
8
let p2 = new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 1000);
});
p2.then((value) => {
console.log(value);
});

原因是执行 .then 函数的时候 Promise 状态是 Pending ,当前我在 Promise.then 方法中只写了 状态为 FULFILLED 和 REJECTED 的处理

所以.then 函数还要处理状态位 PENDING 的处理,pending 状态下,将.then 函数的入参先放在数组中,在异步执行 resolve 是调用

还有问题吗?

有的

then 异步

1
2
3
4
5
6
7
8
9
10
console.log(1);
let p2 = new Promise((resolve) => {
resolve(4);
console.log(2);
});
p2.then((value) => {
console.log(value);
});
console.log(3);
// 1,2,3,4

正常返回 1,2,3,4 现在我写的 promise 返回 1、2、4、3

什么原因呢?原因是 .then 中的函数立即执行了,这不符合标准呀,解决办法是给 .then 函数添加 setTimeout 模拟异步

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
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}

if (this.state === FULFILLED) {
setTimeout(() => {
onFulfilled(this.value);
});
}

if (this.state === REJECTED) {
setTimeout(() => {
onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason);
});
});
}
let promise2 = new Promise(() => {});
return promise2;
}
}

Promise 的数组需要在 constructor 中声明,并且在 resolve 中执行,所以代码 Promise 到这里全部代码如下:

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
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
class Promise {
constructor(executor) {
if (typeof executor !== "function") {
return new TypeError(`Promise resolver ${executor} is not a function`);
}
this.state = PENDING;
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach((fn) => fn());
}
};
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach((fn) => fn());
}
};
try {
executor(resolve, reject);
} catch (e) {
this.reject(e);
}
}

then(onFulfilled, onRejected) {
if (typeof onFulfilled !== "function") {
onFulfilled = (value) => value;
}
if (typeof onRejected !== "function") {
onRejected = (err) => {
throw err;
};
}

if (this.state === FULFILLED) {
setTimeout(() => {
onFulfilled(this.value);
});
}

if (this.state === REJECTED) {
setTimeout(() => {
onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason);
});
});
}
}
}

写到这里,我去测试了一下显示有 806 个异常;也就是说通过了 66 个测试用例。继续努力

then 如何返回一个新的 Promise

接着看规范描述:

then 方法必须返回一个 promise 对象

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
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}


if (this.state === FULFILLED) {
setTimeout(() => {
onFulfilled(this.value);
});
}

if (this.state === REJECTED) {
setTimeout(() => {
onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
onRejected(this.reason);
});
});
}
// 返回一个新的 promise 对象
let promise2 = new Promise(() => {});
return promise2;
}

可以理解吧?每次 .then 都返回一个新的 promise 对象,.then 方法是不是就可以一直调用下去了

这里为什么不可以直接返回 this,比如 jQuery 不就是直接返回 this 实现链式调用的吗?

因为 promise 有 3 种状态,且状态不可逆,所以必须返回一个新的 promise 对象

then 返回 Promise 解决过程

接着看规范描述:

  • 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
  • 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
  • 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
  • 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因

第一句

需要确定, onFulfilled 或者 onRejected 返回一个值 x 要执行 Promise2

修改 then 代码如下:

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
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}

let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
const x = onFulfilled(this.value);
});
}

if (this.state === REJECTED) {
setTimeout(() => {
const x = onRejected(this.reason);
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
const x = onFulfilled(this.value);
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
const x = onRejected(this.reason);
});
});
}
});
return promise2;
}
}

第二句

如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e

使用 try/catch 捕捉 onFulfilled 或者 onRejected 抛出的异常

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
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}

let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
} catch (error) {
reject(error);
}
});
}

if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}

第三句

如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值

promise2 执行成功并返回值,这句简单,在返回 x 的地方直接 resolve(x) 不就可以了吗?

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
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}

let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
});
}

if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
// 这里直接 resolve 并并且返回 x
resolve(x);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}

如果 x 是基本数据类型可以,考虑一下,如果 x 是引用数据类型,是函数,甚至是 Promise 呢?

所以这里需要对 x 的数据类型判断

既然自成一体,索性增加一个方法执行这些 x 值

方法名为:resolvePromise

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
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value;
}
if (typeof onRejected !== 'function') {
onRejected = (err) => {
throw err;
};
}

let promise2 = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}

if (this.state === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
});
return promise2;
}

function resolvePromise(promise2, x, resolve, reject){

}

resolvePromise

接下来开始写 resolvePromise 这个函数

判断 x 只不是 promise 自己

promise 不能循环调用,

1
2
3
4
5
6
7
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
}

判断 x 是不是引用数据类型

如果不是引用数据类型,直接执行 resolve(x)

1
2
3
4
5
6
7
8
9
10
11
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
} else {
resolve(x);
}
}

如果是引用数据类型,判断数据中是否有 then 这个属性,如果有 then 不是函数,直接执行 resolve(x)

这里解释一下:如果 then 是函数,表示 x 可能是 Promise 对象,需要特殊处理,如果不是函数,当作一般对象处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
const then = x.then;
if (typeof then !== "function") {
resolve(x);
} else {
}
} else {
resolve(x);
}
}

当然,只要是代码就有可能出现异常,所以这里需要 try/catch 捕捉一些可能的异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
try {
const then = x.then;
if (typeof then !== "function") {
resolve(x);
} else {
}
} catch (err) {
reject(err);
}
} else {
resolve(x);
}
}

如果 then 是函数

then 是函数,执行 then。因为此时的 then 是从 x 上获取的,所以要调用 call 方法将 then 函数的 this 重新指向 x

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
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if ((typeof x === "object" && x !== null) || typeof x === "function") {
try {
const then = x.then;
if (typeof then !== "function") {
resolve(x);
} else {
then.call(
x,
(value) => {
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
reject(reason);
}
);
}
} catch (err) {
reject(err);
}
} else {
resolve(x);
}
}

上述代码基本完成了 Promise 的功能,但是还有一点规范文档上说:
如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用

这需要增加标识位 calledcalledcalled , called 为 true 直接返回,

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
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x)
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);

if ((typeof x === "object" && x !== null) || typeof x === "function") {
let called;
try {
const then = x.then;
if (typeof then !== "function") resolve(x);
else {
then.call(
x,
(value) => {
if (called) return;
called = true;

resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
}
);
}
} catch (err) {
if (called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
};

作者:北斗落凡尘
链接:https://juejin.cn/post/7065693195799265287

  • 版权声明: 本博客所有文章,未经许可,任何单位及个人不得做营利性使用!转载请标明出处!如有侵权请联系作者。
  • Copyrights © 2015-2023 翟天野

请我喝杯咖啡吧~