Promise 是ES6新增的新语法,解决了回调地狱的问题。

可以把Promise看成一个状态机,初始是pending状态, 可以通过函数resolvereject ,将状态转变为resolved或者rejected状态, 状态一旦改变就不能再次变化。

then函数会返回一个Promise实例, 并且该返回值是一个新的实例,而不是之前的实例。因为Promise规范规定除了pending状态,其他状态是不可以改变的,如果返回的是一个相同实例的话,多个then调用就失去了意义。

对于then来说,本质上可以把它看成是flatMap

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
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
// 三种状态
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
// promise 接收一个函数作为参数,该函数会立即执行
function MyPromise(fn) {
let _this = this
_this.currentState = PENDING
_this.value = undefined
// 用于保存then中的回调,只有当promise状态为pending时才会缓存,并且每个实例至多缓存一个
_this.resolvedCallbacks = []
_this.rejectedCallbacks = []

_this.resolve = function (value) {
if (value instanceof MyPromise) {
// 如果 value 是个 Promise 则递归执行
return value.then(_this.resolve, _this.reject)
}
setTimeout(() => {
// 异步执行,保证执行顺序
if (_this.currentState === PENDING) {
_this.currentState = RESOLVED
_this.value = value
_this.resolvedCallbacks.forEach(cb => cb())
}
})
}

_this.reject = function (reason) {
setTimeout(() => {
// 异步执行,保证执行顺序
if (_this.currentState === PENDING) {
_this.currentState = REJECTED
_this.value = value
_this.rejectedCallbacks.forEach(cb => cb())
}
})
}

// 用于解决以下问题
// new Promise(() => throw Error('error'))
try {
fn(_this.resolve, _this.reject)
} catch (e) {
_this.reject(e)
}
}
MyPromise.prototype.then = function (onResolved, onRejected) {
var slef = this
// 规范 2.2.7 then必须返回的是一个新的promise
var promise2
// 规范2.2.x onResolved 和 onRejected 都为可选参数
// 如果类型不是函数需要忽略,同时也实现了透传
// Promise.resolve(4).then().then((value) => console.log(value))
onResolved = typeof onResolved === 'function' ? onResolved : v => v
onRejected = typeof onRejected === 'function' ? onRejected : r => throw r
if (self.currentState === RESOLVED) {
return (promise2 = new MyPromise(function (resolve, reject) {
// 规范 2.2.4,保证 onFulfilled,onRjected 异步执行
// 所以用了 setTimeout 包裹下
setTimeout(function () {
try {
var x = onResolved(self.value)
resolutionProcedure(promise2, x, resolve, reject)
} catch (reason) {
reject(reason)
}
})
}))
}

if (self.currentState === REJECTED) {
return (promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
// 异步执行onRejected
try {
var x = onRejected(self.value)
resolutionProcedure(promise2, x, resolve, reject)
} catch (reason) {
reject(reason)
}
})
}))
}

if (self.currentState === PENDING) {
return (promise2 = new MyPromise(function (resolve, reject) {
self.resolvedCallbacks.push(function () {
// 考虑到可能会有报错,所以使用 try/catch 包裹
try {
var x = onResolved(self.value)
resolutionProcedure(promise2, x, resolve, reject)
} catch (r) {
reject(r)
}
})

self.rejectedCallbacks.push(function () {
try {
var x = onRejected(self.value)
resolutionProcedure(promise2, x, resolve, reject)
} catch (r) {
reject(r)
}
})
}))
}
}
// 规范 2.3
function resolutionProcedure(promise2, x, resolve, reject) {
// 规范 2.3.1,x 不能和 promise2 相同,避免循环引用
if (promise2 === x) {
return reject(new TypeError("Error"))
}
// 规范 2.3.2
// 如果 x 为 Promise,状态为 pending 需要继续等待否则执行
if (x instanceof MyPromise) {
if (x.currentState === PENDING) {
x.then(function (value) {
// 再次调用该函数是为了确认 x resolve 的
// 参数是什么类型,如果是基本类型就再次 resolve
// 把值传给下个 then
resolutionProcedure(promise2, value, resolve, reject)
}, reject)
} else {
x.then(resolve, reject)
}
return
}
// 规范 2.3.3.3.3
// reject 或者 resolve 其中一个执行过得话,忽略其他的
let called = false
// 规范 2.3.3,判断 x 是否为对象或者函数
if (x !== null && (typeof x === "object" || typeof x === "function")) {
// 规范 2.3.3.2,如果不能取出 then,就 reject
try {
// 规范 2.3.3.1
let then = x.then
// 如果 then 是函数,调用 x.then
if (typeof then === "function") {
// 规范 2.3.3.3
then.call(
x,
y => {
if (called) return
called = true
// 规范 2.3.3.3.1
resolutionProcedure(promise2, y, resolve, reject)
},
e => {
if (called) return
called = true
reject(e)
}
)
} else {
// 规范 2.3.3.4
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
// 规范 2.3.4,x 为基本类型
resolve(x)
}
}