# 手写 Promise
Promise 是 JS 中进行异步编程的新的解决方案(旧的是纯回调函数)。
从语法上讲, Promise 是一个构造函数;从功能上说, Promise 对象用来封装一个异步操作并可以获取其结果。
优势
- 指定回调函数的方式更加灵活(比解决回调地狱更能体现个人技术深度)
- 纯回调方式必须在启动异步任务之前指定
- Promise 指定时机更加灵活,甚至可以在异步任务结束后指定
- Promise 可指定多个回调函数
- 支持链式调用
- 纯回调方式会引发回调地狱问题
// 定义 Promise 的三种状态
const PENDING = 'pending',
FULFILLED = 'fulfilled',
REJECTED = 'rejected'
class Promise {
/**
* @description:
* @param {Function} exe 初始执行函数,是同步的
* @return {*}
*/
constructor(exe) {
// 初始化一些数据
this.data = null
this.callbacks = []
this.status = PENDING
const resolve = (value) => {
if (this.status !== PENDING) return;
this.status = FULFILLED
this.data = value
this.callbacks.forEach(cb => {
setTimeout(() => cb.onFulfilled())
})
}
const reject = (reason) => {
if (this.status !== PENDING) return;
this.status = REJECTED
this.data = reason
this.callbacks.forEach(cb => {
setTimeout(() => cb.onRejected())
})
}
try {
exe(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
// 如果没有传相应回调函数,则给其一个默认函数,使得 then 链能够往下传
onFulfilled = typeof onFulfilled === 'function' ?
onFulfilled : value => value
onRejected = typeof onRejected === 'function' ?
onRejected : reason => {
throw reason
}
return new Promise((resolve, reject) => {
// 工具函数
const handler = (cb) => {
try {
// 获取回调结果
const res = cb(this.data)
// 如果返回值是 Promise ,则进行链式调用
if (res instanceof Promise) {
res.then(resolve, reject)
} else {
// 否则, 直接返回结果
resolve(res)
}
} catch (e) {
reject(e)
}
}
if (this.status === FULFILLED) {
setTimeout(() => handler(onFulfilled))
} else if (this.status === REJECTED) {
setTimeout(() => handler(onRejected))
} else {
// 如果状态还未改变, 先把回调函数保存起来
this.callbacks.push({
onFulfilled: () => {
handler(onFulfilled)
},
onRejected: () => {
handler(onRejected)
}
})
}
})
}
// catch 是 then 的简版
catch (onRejected) {
return this.then(null, onRejected)
}
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
/**
* @description:
* @param {[Promise]} promises
* @return {Promise}
*/
static all(promises) {
return new Promise((resolve, reject) => {
const n = promises.length
const res = new Array(n) // 存储结果
let count = 0 // 计数器
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(
value => {
res[index] = value
count++
if (count === n) resolve(res)
},
reason => reject(reason)
)
})
})
}
static race(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promise => {
Promise.resolve(promise).then(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
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
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