手写Promise及其方法

一、Promise-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
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
/**
* promise实例的状态常量
*/

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

/**
* 处理then函数的参数(onfulfilled,onrejected)的执行结果
*/

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'
) {
let called = false // 防止多次调用成功或失败
try {
let then = x.then
if (typeof then === 'function') {
then.call(x,
y => {
if (called) return
called = true
resolvePromise(promise2, y, resolve, reject)
},
r => {
if (called) return
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}

class Promise {

constructor (executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined

this.onfulfilledCallback = []
this.onrejectedCallback = []

const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.onfulfilledCallback.forEach(fn => fn())
}
}

const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.onrejectedCallback.forEach(fn => fn())
}
}

try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}

then (onfulfilled, onrejected) {

onfulfilled = typeof onfulfilled === 'function'
? onfulfilled
: value => value

onrejected = typeof onrejected === 'function'
? onrejected
: err => { throw err }

const promise2 = new Promise((resolve, reject) => {

if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = onfulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}

if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onrejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}

if (this.status === PENDING) {
this.onfulfilledCallback.push(() => {
setTimeout(() => {
try {
const x = onfulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})

this.onrejectedCallback.push(() => {
setTimeout(() => {
try {
const x = onrejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})

return promise2
}
}

/**
* 用于promises-aplus-tests
*/

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

// module.exports = Promise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 判断一个值是否是promise实例
*/

const isPromise = (value) => {
if (
(typeof value === 'object' && value !== null)
|| typeof value === 'function'
) {
if (typeof value.then === 'function') {
return true
} else {
return false
}
} else {
return false
}
}

二、catch-finally

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Promise{
// ...

catch (onrejected) {
return this.then(null, onrejected)
}

finally (cb) {
return this.then(
res => Promise.resolve(cb()).then(() => res),
err => Promise.resolve(cb()).catch(() => err)
)
}
}

三、resolve-reject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Promise{
// ...

static resolve (value) {
return new Promise((resolve, reject) => {
if (isPromise(value)) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}

static reject (value) {
return new Promise((resolve, reject) => {
reject(value)
})
}
}

四、race

Promise.race:谁先改变状态就返回谁的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Promise{
// ...

static race (values) {
return new Promise((resolve, reject) => {
for (let i = 0; i < values.length; i++) {
const cur = values[i]
if (isPromise(cur)) {
cur.then(resolve, reject)
} else {
resolve(cur)
}
}
})
}
}

五、all

Promise.all:状态都是fulfilled,返回所有结果,有一个rejected,就返回rejected结果。

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
class Promise{
// ...

static all (values) {
return new Promise((resolve, reject) => {

let ret = []
let index = 0

function processData (i, val) {
ret[i] = val
if (++index === values.length) {
resolve(ret)
}
}

for (let i = 0; i < values.length; i++) {
const cur = values[i]
if (isPromise(cur)) {
cur.then(val => {
processData(i, val)
}, reject)
} else {
processData(i, cur)
}
}
})
}
}

六、allSettled

Promise.allSettled:状态总是fulfilled,记录所有成功失败结果。

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
class Promise{
// ...

static allSettled (values) {
return new Promise((resolve, reject) => {
let ret = []
let index = 0

function processData (i, val, type) {
ret[i] = {
status: type === 'value' ? FULFILLED : REJECTED,
[type]: val
}
if (++index === values.length) {
resolve(ret)
}
}

for (let i = 0; i < values.length; i++) {
const cur = values[i]
if (isPromise(cur)) {
cur.then(res => {
processData(i, res, 'value')
}, err => {
processData(i, err, 'reason')
})
} else {
processData(i, cur, 'value')
}
}
})
}
}

七、any

Promise.any:有一个fulfilled,就返回fulfilled的结果,都rejected,则返回rejecte。

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
class Promise{
// ...

static any (values) {
return new Promise((resolve, reject) => {
let errData = []
let index = 0

function processError (i, err) {
errData[i] = err

if (++index === values.length) {
reject("AggregateError: All promises were rejected")
}
}

for (let i = 0; i < values.length; i++) {
const cur = values[i]
if (isPromise(cur)) {
cur.then(resolve, err => {
processError(i, err)
})
} else {
resolve(cur)
}
}
})
}
}

参考链接