Promise的具体实现

一、目标效果

本篇文章将实现一个名为MyPromise的类,可以实现如下的调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})


var p2 = p1.then(res => {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(res + 1)
}, 1000)
})
})
.then(res => {
console.log(res)
return res + 1
})

p1.then(res => {
console.log(res)
})

二、代码实现

本实例会实现Promise的构造函数,then函数,resolve和reject,以及all和race。

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
137
138
139
140
141
142
// promise的三种状态
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

class MyPromise {
constructor(fn) {
this.status = PENDING

// 用于保存传入的值
this.value = value
// 用于保存失败的日志
this.reason = reason

// 用于保存链式调用中的resolve和reject回调函数
this.resolveCallbacks = []
this.rejectCallbacks = []

// 解决时触发的函数
const resolve = value => {
// 改变状态
if (this.status === PENDING) {
this.status = FULFILLED
// 保存数据
this.value = value
// 解决之后出发链式调用,将值传给后续promise
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}

// 失败时触发的函数
const reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.rejectCallbacks.forEach(fn => fn(this.reason))
}
}

try {
fn(resolve, reject)
}
catch(err) {
reject(err)
}
}

then(onFulfilled, onRejected) {
// 判断传入值是不是函数,如果不是,就包装成函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw(new Error(reason)) }

// 保存上一个promise的this
const self = this

// then本质上是返回一个promise实例
return new MyPromise((resolve, reject) => {
let fulfilled = () => {
try {
const result = onFulfilled(self.value)
// 如果回调函数返回的又是一个promise实例,就把它当作then处理
return result instanceof MyPromise ? result.then(resolve, reject) : resolve(result)
}
catch (err) {
reject(err)
}
}

let rejected = () => {
try {
const result = onRejected(self.value)
return result instanceof MyPromise ? result.then(resolve, reject) : reject(result)
}
}

// 根据上一个promise状态来判断是否执行当前promise
switch(self.status) {
// 如果是PENDING状态,则暂存在数组种
case PENDING:
self.resolveCallbacks.push(fulfilled)
self.rejectCallbacks.push(rejected)
break
case FULFILLED:
fulfilled()
break
case REJECTED:
rejected()
break
}
})
}

// catch其实就是将参数透传给then
catch(onRejected) {
return this.then(null, onRejected)
}

// 将传入的值包装成Promise实例,并调用resolve
static resolve(value) {
if (value instanceof MyPromise) {
return value
}
else {
return new MyPromise((resolve, reject) => resolve(value))
}
}

static reject(reason) {
return new MyPromise((resolve, reject) => reject(reason))
}

static all(promiseArr) {
const len = promiseArr.length
const values = new Array(len)

let count = 0

return new MyPromise((resolve, reject) => {
for (let i = 0; i < len; i ++) {
MyPromise.resolve(promiseArr[i]).then(val => {
values[i] = val
count ++
if (count === len) resolve(values) // 当所有promise执行完的时候,将保存所有值的values向外传递
},
err => {
reject(err)
})
}
})
}

static race(promiseArr) {
return new MyPromise((resolve, reject) => {
promiseArr.forEach(item => {
MyPromise.resolve(item).then(
val => resolve(val),
err => reject(err)
)
})
})
}
}

参考:

Promise.then是如何实现链式调用的


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!