# 深入探究 Promise 原理
这里只介绍 Promise 的基本思想和代码实现,不对其用法做说明。末尾附上 PromiseA+ 实现源码。
# 1. Promise
基本结构
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('FULFILLED')
}, 1000)
})
2
3
4
5
构造函数
Promise
必须接受一个函数作为参数,我们称该函数为handle
,handle
又包含resolve
和reject
两个参数,它们是两个函数。
定义一个判断一个变量是否为函数的方法,后面会用到
// 判断变量否为function
const isFunction = variable => typeof variable === 'function'
2
首先,我们定义一个名为 MyPromise
的 Class
,它接受一个函数 handle
作为参数
class MyPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
}
}
2
3
4
5
6
7
再往下看
# 2. Promise
状态和值
Promise
对象存在以下三种状态:
Pending(进行中)
Fulfilled(已成功)
Rejected(已失败)
状态只能由
Pending
变为Fulfilled
或由Pending
变为Rejected
,且状态改变之后不会在发生变化,会一直保持这个状态。
Promise
的值是指状态改变时传递给回调函数的值
上文中
handle
函数包含resolve
和reject
两个参数,它们是两个函数,可以用于改变Promise
的状态和传入Promise
的值
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('FULFILLED')
}, 1000)
})
2
3
4
5
这里 resolve
传入的 "FULFILLED"
就是 Promise
的值
resolve` 和 `reject
resolve
: 将Promise对象的状态从Pending(进行中)
变为Fulfilled(已成功)
reject
: 将Promise对象的状态从Pending(进行中)
变为Rejected(已失败)
resolve
和reject
都可以传入任意类型的值作为实参,表示Promise
对象成功(Fulfilled)
和失败(Rejected)
的值
了解了 Promise
的状态和值,接下来,我们为 MyPromise
添加状态属性和值
首先定义三个常量,用于标记Promise对象的三种状态
// 定义Promise的三种状态常量
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
2
3
4
再为
MyPromise
添加状态和值,并添加状态改变的执行逻辑
class MyPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
// 添加状态
this._status = PENDING
// 添加状态
this._value = undefined
// 执行handle
try {
handle(this._resolve.bind(this), this._reject.bind(this))
} catch (err) {
this._reject(err)
}
}
// 添加resovle时执行的函数
_resolve (val) {
if (this._status !== PENDING) return
this._status = FULFILLED
this._value = val
}
// 添加reject时执行的函数
_reject (err) {
if (this._status !== PENDING) return
this._status = REJECTED
this._value = err
}
}
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
这样就实现了 Promise
状态和值的改变。下面说一说 Promise
的核心: then
方法
# 3. Promise
的 then
方法
Promise
对象的 then
方法接受两个参数:
promise.then(onFulfilled, onRejected)
参数可选
onFulfilled
和 onRejected
都是可选参数。
- 如果
onFulfilled
或onRejected
不是函数,其必须被忽略
onFulfilled
特性
如果 onFulfilled
是函数:
- 当
promise
状态变为成功时必须被调用,其第一个参数为promise
成功状态传入的值(resolve
执行时传入的值) - 在
promise
状态改变前其不可被调用 - 其调用次数不可超过一次
onRejected
特性
如果 onRejected
是函数:
- 当
promise
状态变为失败时必须被调用,其第一个参数为promise
失败状态传入的值(reject
执行时传入的值) - 在
promise
状态改变前其不可被调用 - 其调用次数不可超过一次
多次调用
then
方法可以被同一个 promise
对象调用多次
- 当
promise
成功状态时,所有onFulfilled
需按照其注册顺序依次回调 - 当
promise
失败状态时,所有onRejected
需按照其注册顺序依次回调
返回
then
方法必须返回一个新的 promise
对象
promise2 = promise1.then(onFulfilled, onRejected);
因此 promise
支持链式调用
promise1.then(onFulfilled1, onRejected1).then(onFulfilled2, onRejected2);
这里涉及到 Promise
的执行规则,包括“值的传递”和“错误捕获”机制:
1、如果 onFulfilled
或者 onRejected
返回一个值 x
,则运行下面的 Promise
解决过程:[[Resolve]](promise2, x)
- 若
x
不为Promise
,则使x
直接作为新返回的Promise
对象的值, 即新的onFulfilled
或者onRejected
函数的参数. - 若
x
为Promise
,这时后一个回调函数,就会等待该Promise
对象(即x
)的状态发生变化,才会被调用,并且新的Promise
状态和x
的状态相同。
下面的例子用于帮助理解:
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
})
promise2 = promise1.then(res => {
// 返回一个普通值
return '这里返回一个普通值'
})
promise2.then(res => {
console.log(res) //1秒后打印出:这里返回一个普通值
})
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
})
promise2 = promise1.then(res => {
// 返回一个Promise对象
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('这里返回一个Promise')
}, 2000)
})
})
promise2.then(res => {
console.log(res) //3秒后打印出:这里返回一个Promise
})
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
2、如果 onFulfilled
或者onRejected
抛出一个异常 e
,则 promise2
必须变为失败(Rejected)
,并返回失败的值 e
,例如:
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
promise2 = promise1.then(res => {
throw new Error('这里抛出一个异常e')
})
promise2.then(res => {
console.log(res)
}, err => {
console.log(err) //1秒后打印出:这里抛出一个异常e
})
2
3
4
5
6
7
8
9
10
11
12
13
3、如果onFulfilled
不是函数且 promise1
状态为成功(Fulfilled)
, promise2
必须变为成功(Fulfilled)
并返回 promise1
成功的值,例如:
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
promise2 = promise1.then('这里的onFulfilled本来是一个函数,但现在不是')
promise2.then(res => {
console.log(res) // 1秒后打印出:success
}, err => {
console.log(err)
})
2
3
4
5
6
7
8
9
10
11
12
4、如果 onRejected
不是函数且 promise1
状态为失败(Rejected)
,promise2
必须变为失败(Rejected)
并返回 promise1
失败的值,例如:
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('fail')
}, 1000)
})
promise2 = promise1.then(res => res, '这里的onRejected本来是一个函数,但现在不是')
promise2.then(res => {
console.log(res)
}, err => {
console.log(err) // 1秒后打印出:fail
})
2
3
4
5
6
7
8
9
10
11
12
根据上面的规则,我们来为 完善 MyPromise
修改 constructor
: 增加执行队列
由于 then
方法支持多次调用,我们可以维护两个数组,将每次 then
方法注册时的回调函数添加到数组中,等待执行
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
// 添加状态
this._status = PENDING
// 添加状态
this._value = undefined
// 添加成功回调函数队列
this._fulfilledQueues = []
// 添加失败回调函数队列
this._rejectedQueues = []
// 执行handle
try {
handle(this._resolve.bind(this), this._reject.bind(this))
} catch (err) {
this._reject(err)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
添加then方法
首先,then
返回一个新的 Promise
对象,并且需要将回调函数加入到执行队列中
// 添加then方法
then (onFulfilled, onRejected) {
const { _value, _status } = this
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(onFulfilled)
this._rejectedQueues.push(onRejected)
break
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
onFulfilled(_value)
break
case REJECTED:
onRejected(_value)
break
}
// 返回一个新的Promise对象
return new MyPromise((onFulfilledNext, onRejectedNext) => {
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
那返回的新的 Promise
对象什么时候改变状态?改变为哪种状态呢?
根据上文中 then
方法的规则,我们知道返回的新的 Promise
对象的状态依赖于当前 then
方法回调函数执行的情况以及返回值,例如 then
的参数是否为一个函数、回调函数执行是否出错、返回值是否为 Promise
对象。
我们来进一步完善 then
方法:
// 添加then方法
then (onFulfilled, onRejected) {
const { _value, _status } = this
// 返回一个新的Promise对象
return new MyPromise((onFulfilledNext, onRejectedNext) => {
// 封装一个成功时执行的函数
let fulfilled = value => {
try {
if (!isFunction(onFulfilled)) {
onFulfilledNext(value)
} else {
let res = onFulfilled(value);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(onFulfilledNext, onRejectedNext)
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
onFulfilledNext(res)
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
onRejectedNext(err)
}
}
// 封装一个失败时执行的函数
let rejected = error => {
try {
if (!isFunction(onRejected)) {
onRejectedNext(error)
} else {
let res = onRejected(error);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(onFulfilledNext, onRejectedNext)
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
onFulfilledNext(res)
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
onRejectedNext(err)
}
}
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(fulfilled)
this._rejectedQueues.push(rejected)
break
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
fulfilled(_value)
break
case REJECTED:
rejected(_value)
break
}
})
}
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
这一部分可能不太好理解,读者需要结合上文中
then
方法的规则来细细的分析。
接着修改 _resolve
和 _reject
:依次执行队列中的函数
当 resolve
或 reject
方法执行时,我们依次提取成功或失败任务队列当中的函数开始执行,并清空队列,从而实现 then
方法的多次调用,实现的代码如下:
// 添加resovle时执行的函数
_resolve (val) {
if (this._status !== PENDING) return
// 依次执行成功队列中的函数,并清空队列
const run = () => {
this._status = FULFILLED
this._value = val
let cb;
while (cb = this._fulfilledQueues.shift()) {
cb(val)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(() => run(), 0)
}
// 添加reject时执行的函数
_reject (err) {
if (this._status !== PENDING) return
// 依次执行失败队列中的函数,并清空队列
const run = () => {
this._status = REJECTED
this._value = err
let cb;
while (cb = this._rejectedQueues.shift()) {
cb(err)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(run, 0)
}
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
这里还有一种特殊的情况,就是当 resolve
方法传入的参数为一个 Promise
对象时,则该 Promise
对象状态决定当前 Promise
对象的状态。
const p1 = new Promise(function (resolve, reject) {
// ...
});
const p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1);
})
2
3
4
5
6
7
8
9
上面代码中,p1
和 p2
都是 Promise
的实例,但是 p2
的resolve
方法将 p1
作为参数,即一个异步操作的结果是返回另一个异步操作。
注意,这时 p1
的状态就会传递给 p2
,也就是说,p1
的状态决定了 p2
的状态。如果 p1
的状态是Pending
,那么 p2
的回调函数就会等待 p1
的状态改变;如果 p1
的状态已经是 Fulfilled
或者 Rejected
,那么 p2
的回调函数将会立刻执行。
我们来修改_resolve
来支持这样的特性
// 添加resovle时执行的函数
_resolve (val) {
const run = () => {
if (this._status !== PENDING) return
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = (value) => {
let cb;
while (cb = this._fulfilledQueues.shift()) {
cb(value)
}
}
// 依次执行失败队列中的函数,并清空队列
const runRejected = (error) => {
let cb;
while (cb = this._rejectedQueues.shift()) {
cb(error)
}
}
/* 如果resolve的参数为Promise对象,则必须等待该Promise对象状态改变后,
当前Promsie的状态才会改变,且状态取决于参数Promsie对象的状态
*/
if (val instanceof MyPromise) {
val.then(value => {
this._value = value
this._status = FULFILLED
runFulfilled(value)
}, err => {
this._value = err
this._status = REJECTED
runRejected(err)
})
} else {
this._value = val
this._status = FULFILLED
runFulfilled(val)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(run, 0)
}
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
这样一个Promise就基本实现了,现在我们来加一些其它的方法
catch
方法
相当于调用
then
方法, 但只传入Rejected
状态的回调函数
// 添加catch方法
catch (onRejected) {
return this.then(undefined, onRejected)
}
2
3
4
5
静态 resolve
方法
// 添加静态resolve方法
static resolve (value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
2
3
4
5
6
7
静态 reject
方法
// 添加静态reject方法
static reject (value) {
return new MyPromise((resolve ,reject) => reject(value))
}
2
3
4
5
静态 all
方法
// 添加静态all方法
static all (list) {
return new MyPromise((resolve, reject) => {
/**
* 返回值的集合
*/
let values = []
let count = 0
for (let [i, p] of list.entries()) {
// 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
this.resolve(p).then(res => {
values[i] = res
count++
// 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
if (count === list.length) resolve(values)
}, err => {
// 有一个被rejected时返回的MyPromise状态就变成rejected
reject(err)
})
}
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
静态 race
方法
// 添加静态race方法
static race (list) {
return new MyPromise((resolve, reject) => {
for (let p of list) {
// 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
this.resolve(p).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
2
3
4
5
6
7
8
9
10
11
12
13
14
finally
方法
finally
方法用于指定不管Promise
对象最后状态如何,都会执行的操作
finally (cb) {
return this.then(
value => MyPromise.resolve(cb()).then(() => value),
reason => MyPromise.resolve(cb()).then(() => { throw reason })
);
};
2
3
4
5
6
7
这样一个完整的 Promsie
就实现了,大家对 Promise
的原理也有了解,可以让我们在使用Promise的时候更加清晰明了。
完整代码如下
// 判断变量否为function
const isFunction = variable => typeof variable === 'function'
// 定义Promise的三种状态常量
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class MyPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
// 添加状态
this._status = PENDING
// 添加状态
this._value = undefined
// 添加成功回调函数队列
this._fulfilledQueues = []
// 添加失败回调函数队列
this._rejectedQueues = []
// 执行handle
try {
handle(this._resolve.bind(this), this._reject.bind(this))
} catch (err) {
this._reject(err)
}
}
// 添加resovle时执行的函数
_resolve (val) {
const run = () => {
if (this._status !== PENDING) return
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = (value) => {
let cb;
while (cb = this._fulfilledQueues.shift()) {
cb(value)
}
}
// 依次执行失败队列中的函数,并清空队列
const runRejected = (error) => {
let cb;
while (cb = this._rejectedQueues.shift()) {
cb(error)
}
}
/* 如果resolve的参数为Promise对象,则必须等待该Promise对象状态改变后,
当前Promsie的状态才会改变,且状态取决于参数Promsie对象的状态
*/
if (val instanceof MyPromise) {
val.then(value => {
this._value = value
this._status = FULFILLED
runFulfilled(value)
}, err => {
this._value = err
this._status = REJECTED
runRejected(err)
})
} else {
this._value = val
this._status = FULFILLED
runFulfilled(val)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(run, 0)
}
// 添加reject时执行的函数
_reject (err) {
if (this._status !== PENDING) return
// 依次执行失败队列中的函数,并清空队列
const run = () => {
this._status = REJECTED
this._value = err
let cb;
while (cb = this._rejectedQueues.shift()) {
cb(err)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(run, 0)
}
// 添加then方法
then (onFulfilled, onRejected) {
const { _value, _status } = this
// 返回一个新的Promise对象
return new MyPromise((onFulfilledNext, onRejectedNext) => {
// 封装一个成功时执行的函数
let fulfilled = value => {
try {
if (!isFunction(onFulfilled)) {
onFulfilledNext(value)
} else {
let res = onFulfilled(value);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(onFulfilledNext, onRejectedNext)
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
onFulfilledNext(res)
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
onRejectedNext(err)
}
}
// 封装一个失败时执行的函数
let rejected = error => {
try {
if (!isFunction(onRejected)) {
onRejectedNext(error)
} else {
let res = onRejected(error);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(onFulfilledNext, onRejectedNext)
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
onFulfilledNext(res)
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
onRejectedNext(err)
}
}
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(fulfilled)
this._rejectedQueues.push(rejected)
break
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
fulfilled(_value)
break
case REJECTED:
rejected(_value)
break
}
})
}
// 添加catch方法
catch (onRejected) {
return this.then(undefined, onRejected)
}
// 添加静态resolve方法
static resolve (value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
// 添加静态reject方法
static reject (value) {
return new MyPromise((resolve ,reject) => reject(value))
}
// 添加静态all方法
static all (list) {
return new MyPromise((resolve, reject) => {
/**
* 返回值的集合
*/
let values = []
let count = 0
for (let [i, p] of list.entries()) {
// 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
this.resolve(p).then(res => {
values[i] = res
count++
// 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
if (count === list.length) resolve(values)
}, err => {
// 有一个被rejected时返回的MyPromise状态就变成rejected
reject(err)
})
}
})
}
// 添加静态race方法
static race (list) {
return new MyPromise((resolve, reject) => {
for (let p of list) {
// 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
this.resolve(p).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
finally (cb) {
return this.then(
value => MyPromise.resolve(cb()).then(() => value),
reason => MyPromise.resolve(cb()).then(() => { throw 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
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# 4.PromiseA+规范实现
直接附上源码
const isFunction = function(fun) {
return typeof fun === 'function';
};
const isObject = function(value) {
return value !== null && typeof value === 'object';
};
// [[Resolve]](promise, x): 是promise的解决过程,判断x的值的类型以及它和promise实例的关系
// 需要进行 [[Resolve]](promise, x)的地方有:
// 1. then中的onFulfilled和onRejected的返回值res:[[Resolve]](promise, res)
// 2. _promiseResolve中,x为Promise的情况,对改promise的值y进行[[Resolve]](promise, y)
// 3. _promiseResolve中,x有then且then为函数的情况,该then的第一个参数是函数resolvePromise接收一个y为参数,对y进行[[Resolve]](promise, y)
class MyPromise {
constructor(handle) {
if (!isFunction(handle)) {
throw new TypeError('MyPromise resolver is not a function');
}
// 当前promise的状态
this._status = 'PENDING';
// 当前promise的值
this._value = undefined;
// promise状态为'FULFILLED'时需要执行的注册事件队列
this._fulfilledQueue = [];
// promise状态为'REJECTED'时需要执行的注册事件队列
this._rejectedQueue = [];
// promise创建后,同步执行handle
// 如果handle执行出错,则将promise的状态改为'REJECTED'
try {
handle(this._resolve.bind(this), this._reject.bind(this));
} catch(err) {
this._reject(err);
}
}
_resolve(value) {
if (this._status !== 'PENDING') {
return;
}
const resolveHandle = (val) => {
this._status = 'FULFILLED';
this._value = val;
while(this._fulfilledQueue.length) {
const cb = this._fulfilledQueue.shift();
cb(val);
}
}
const rejectHandle = (reason) => {
this._status = 'REJECTED';
this._value = reason;
while(this._rejectedQueue.length) {
const cb = this._rejectedQueue.shift();
cb(reason);
}
}
// 判断resolve传入的是不是一个promise
// 如果是,需要等待该promise的状态改变,新promise的状态和该状态相同
// 注意:Promise/A+规范并没有这个规定
if (value instanceof MyPromise) {
if (value === this) {
return rejectHandle(new TypeError(''));
}
value.then(resolveHandle, rejectHandle);
} else {
// 执行_fulfilledQueue中的任务
// 所有 onFulfilled 需按照其注册顺序依次回调
resolveHandle(value);
}
}
_reject(reason) {
if (this._status !== 'PENDING') {
return;
}
this._status = 'REJECTED';
this._value = reason;
// 执行_rejectedQueue中的任务
// 所有的 onRejected 需按照其注册顺序依次回调
while(this._rejectedQueue.length) {
const cb = this._rejectedQueue.shift();
cb(reason);
}
}
// Promise解决过程
// [[Resolve]](promise, x)
_promiseResolve(promise, x, resolve, reject) {
// x与promise相等
// 如果promise和x指向同一对象,以TypeError为reason执行reject
if (x === promise) {
return reject(new TypeError(''));
}
// x为Promise
// 如果 x 为 Promise ,则使 promise 接受 x 的状态
if (x instanceof MyPromise) {
// x的value为y, 运行[[Resolve]](promise, y):this._promiseResolve(promise, y, resolve, reject);
// 有可能是一个promise,所以需要调用解决过程
x.then(
y => {
this._promiseResolve(promise, y, resolve, reject);
},
reject
);
return;
}
// x为对象或函数
if (isFunction(x) || isObject(x)) {
let isCalled = false;
let then;
// 如果取 x.then 的值时抛出错误 e ,则以e为reason执行reject(e)
try {
then = x.then;
} catch(e) {
return reject(e);
}
// 如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise:
// 如果 resolvePromise 以 y 为参数被调用,则运行 [[Resolve]](promise, y): this._promiseResolve(promise, y, resolve, reject);
// 如果 rejectPromise 以 r 为参数被调用,则执行reject(r);
// 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
if (isFunction(then)) {
const resolvePromise = y => {
if (isCalled) {
return;
}
isCalled = true;
this._promiseResolve(promise, y, resolve, reject);
}
const rejectPromise = (r) => {
if (isCalled) {
return;
}
isCalled = true;
reject(r);
}
// 如果调用 then 方法抛出了异常 e
// 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
// 否则以 e 为reason执行reject(e);
try {
then.call(x, resolvePromise, rejectPromise);
} catch(e) {
if (isCalled) {
return;
}
reject(e);
}
// 如果 then 不是函数(包括没有then的情况),以 x 为参数执行resolve(x);
} else {
resolve(x);
}
return;
}
// 如果 x 不为对象或者函数,以 x 为参数执行resolve(x);
resolve(x);
}
then(onFulfilled, onRejected) {
const promise = new MyPromise((resolveNext, rejectedNext) => {
const fulfilledHandle = (value) => {
queueMicrotask(() => {
if (!isFunction(onFulfilled)) {
resolveNext(value);
} else {
try {
const res = onFulfilled(value);
// 执行promise的解决过程
this._promiseResolve(promise, res, resolveNext, rejectedNext);
} catch(err) {
rejectedNext(err);
}
}
});
};
const rejectedHandle = (reason) => {
queueMicrotask(() => {
if (!isFunction(onRejected)) {
rejectedNext(reason);
} else {
try {
const res = onRejected(reason);
// 执行promise的解决过程
this._promiseResolve(promise, res, resolveNext, rejectedNext);
} catch(err) {
rejectedNext(err);
}
}
});
};
switch(this._status) {
// 状态为"PENDING'时,将任务加入到队列中等待promise的状态改变时执行
case 'PENDING':
this._fulfilledQueue.push(fulfilledHandle);
this._rejectedQueue.push(rejectedHandle);
break;
case 'FULFILLED':
fulfilledHandle(this._value);
break;
case 'REJECTED':
rejectedHandle(this._value);
break;
default:
}
});
return promise;
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
// finally返回的新promise的状态取决于调用finally的promise的状态
// finally方法总是会返回原来的值
// 如果cb返回的是一个promise, 会等待该promise的状态改变
finally(cb) {
return this.then(
(value) => MyPromise.resolve(cb()).then(() => value),
(err) => MyPromise.resolve(cb()).then(() => { throw err })
);
}
static resolve(p) {
if (p instanceof MyPromise) {
return p;
}
return new MyPromise((resolve) => {
resolve(p);
});
}
// MyPromise.reject()方法的参数,会原封不动地作为reject的理由, 不会处理传入promise的情况
static reject(p) {
return new MyPromise((resolve, reject) => {
reject(p);
});
}
// 如果不是传入的数组某一项不是MyPromise实例,就会先调用MyPromise.resolve()方法,将参数转为MyPromise实例,再进一步处理
static all(promiseList) {
return new MyPromise((resolve, reject) => {
let list;
// 如果promiseList不是iterator,会报错,直接reject
try {
list = [...promiseList];
} catch(err) {
reject(new TypeError(`${promiseList} is not iterable (cannot read property Symbol(Symbol.iterator))`));
return;
}
const len = list.length;
// promiseList为空数组,resolve
if (len === 0) {
resolve([]);
}
let fulfilledCount = 0;
const res = [];
for (const [i, p] of list.entries()) {
MyPromise.resolve(p)
.then((value) => {
res[i] = value;
fulfilledCount++;
if (fulfilledCount === len) {
resolve(res);
}
}, (err) => {
reject(err);
});
}
});
}
// 如果不是传入的数组某一项不是MyPromise实例,就会先调用MyPromise.resolve()方法,将参数转为MyPromise实例,再进一步处理
static race(promiseList) {
return new MyPromise((resolve, reject) => {
let list;
// 如果promiseList不是iterator,会报错,直接reject
try {
list = [...promiseList];
} catch(err) {
reject(new TypeError(`${promiseList} is not iterable (cannot read property Symbol(Symbol.iterator))`));
return;
}
// 会等待第一个改变状态的promise,如果promiseList为空数组,则会一直是pending状态
for (const p of list) {
MyPromise.resolve(p)
.then((value) => {
resolve(value);
}, (err) => {
reject(err);
});
}
});
}
// MyPromise.allSettled()方法接受一组Promise实例作为参数,f返回一个新的Promise实例,且新实例的状态只可能变成fulfilled
// 只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。该方法由 ES2020 引入。
/** 返回新的promise的结果
* [
{ status: 'fulfilled', value: 42 },
{ status: 'rejected', reason: -1 }
]
*/
static allSettled(promiseList) {
return new MyPromise((resolve, reject) => {
let list;
// 如果promiseList不是iterator,会报错,直接reject
try {
list = [...promiseList];
} catch(err) {
reject(new TypeError(`${promiseList} is not iterable (cannot read property Symbol(Symbol.iterator))`));
return;
}
let unsettledCount = list.length;
// promiseList为空数组,resolve
if (unsettledCount === 0) {
resolve([]);
}
const res = [];
for (const [i, p] of list.entries()) {
MyPromise.resolve(p)
.then(value => {
res[i] = {status: 'fulfilled', value};
}, reason => {
res[i] = {status: 'rejected', reason};
}).finally(() => {
unsettledCount--;
if (unsettledCount === 0) {
resolve(res);
}
});
}
});
}
// 与Promise.all相反,如果有一个为fulfilled,返回的新promise就是fulfilled,否则就是rejected
// 数组为空或者所有promise都是rejected状态,返回一个AggregateError:new AggregateError(errors, 'All promises were rejected')
// errors数组保存每个失败的原因,如果数组为空,则errors为空
static any(promiseList) {
return new MyPromise((resolve, reject) => {
let list;
// 如果promiseList不是iterator,会报错,直接reject
try {
list = [...promiseList];
} catch(err) {
reject(new TypeError(`${promiseList} is not iterable (cannot read property Symbol(Symbol.iterator))`));
return;
}
const len = list.length;
const errors = [];
// promiseList为空数组,表示没有一个promise会是fulfilled状态,所以结果为rejected
if (len === 0) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
let rejectedCount = 0;
for (const [i, p] of list.entries()) {
MyPromise.resolve(p)
.then(
value => {
resolve(value);
},
err => {
errors[i] = err;
rejectedCount++;
if (rejectedCount === len) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
}
);
}
});
}
}
// 测试代码
// MyPromise.deferred = function() {
// var result = {};
// result.promise = new MyPromise(function(resolve, reject){
// result.resolve = resolve;
// result.reject = reject;
// });
// return result;
// }
// var promisesAplusTests = require("promises-aplus-tests");
// const { reject } = require("underscore");
// promisesAplusTests(MyPromise, function (err) {
// console.log(err);
// // All done; output is in the console. Or check `err` for number of failures.
// });
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385