promise基本用法以及手写

简单版

20行手写promise

目前见过最容易理解的promise

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
// promise 1
function Promise(executor) {
// Promise resolve时的回调函数集
this.callbacks = []
const resolve = (val) => {
// 注意promise的then函数需要异步执行
setTimeout(() => {
this.data = val;
// cbs里用户传入的函数执行一遍
this.callbacks.forEach(cb => {
cb(val)
});
}, 0)
}
executor(resolve)
}
Promise.prototype.then = function(onResolved) {
// promise2
return new Promise(function(resolve) {
// this指的是promise1
this.callbacks.push(() => {
// onResolved对应用户在then里传入的函数
const res = onResolved(this.data)
if (res instanceof Promise) {
// 只有promise2被resolve以后
// then下面的链式调用函数才会继续执行
res.then(resolve)
} else {
// onResolved
resolve(res)
}
})
})
}

实例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 500);
})
.then((res) => {
console.log(res);
return new Promise((resolve) => {
setTimeout(() => {
resolve(2);
}, 500);
});
})
.then(console.log);
// 500s后输出 1
// 500s后输出 2

面试版

在基础版基础上增加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
// 进阶版
function cppPromise(executor) {
// 收集链式调用的函数集合cb
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
this.value = undefined
this.reason = undefined
this.status = 'pending'
const resolve = (value) => {
setTimeout(() => {
this.status = 'fulfilled'
this.value = value
this.onResolvedCallbacks.forEach((cb) => {
cb(this.value)
})
}, 0)
}
const reject = (val) => {
setTimeout(() => {
this.status = 'rejected'
this.reason = val
this.onRejectedCallbacks.forEach((cb) => {
cb(this.reason)
})
}, 0)
}
executor(resolve, reject)
}
handleResolve(resolve, reject, onFulledFn) {
return new cppPromise((resolve, reject) => {
setTimeout(() => {
try {
const res = onFulledFn(this.value);
if (res instanceof cppPromise) {
res.then(resolve, reject)
} else {
resolve(res)
}
} catch (e) {
reject(e)
}
})
})
}
handleReject(resolve, reject, onRejectedFn) {
return new cppPromise((resolve, reject) => {
setTimeout(() => {
try {
const res = onRejectedFn(this.reason);
if (res instanceof cppPromise) {
res.then(resolve, reject)
} else {
resolve(res)
}
} catch (e) {
reject(e)
}
})
})
}
cppPromise.prototype.then = function(onFulledFn, onRejectedFn) {
if (this.status === 'pending') {
return new cppPromise((resolve, reject) => {
// 收集成功的回调
this.onResolvedCallbacks.push(() => {
handleResolve(resolve, reject, onFulledFn)
});

// 收集失败的回调
this.onRejectedCallbacks.push(() => {
handleReject(resolve, reject, onRejectedFn)
});
})
}
if (this.status === 'fulfilled') {
return new cppPromise((resolve, reject) => {
setTimeout(() => {
handleResolve(resolve, reject, onFulledFn)
})
})
}
if (this.status === 'rejected') {
return new cppPromise((resolve, reject) => {
setTimeout(() => {
handleReject(resolve, reject, onRejectedFn)
})
})
}
};

示例 2

1
2
3
4
5
6
7
8
9
10
11
12
// 实例调用2
const promise1 = new cppPromise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
const promise2 = promise1.then((res) => {
console.log(res)
throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)

专业版1

手写MockPromise

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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class MockPromise {
constructor(executor) {
this.status = 'pending'
this.value = undefined
this.reason = undefined
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
// 定义resolve
let resolve = (data) => {
if (this.status === 'pending') {
this.status = 'resolve'
this.value = data
this.onResolvedCallbacks.forEach(fn => fn())
}
}
// reject
let reject = (data) => {
if (this.status === 'pending') {
this.status = 'reject'
this.reason = data
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch(e) {
reject(e)
}
}
/**
* @description then函数
* @param {function} onFufilled
* @param {function} onRejected
*/
then(onFufilled, onRejected) {
// console.log(`onFufilled`, onFufilled);
// console.log(`onRejected`, onRejected);
if (typeof onFufilled !== 'function') {
onFufilled = res => res
}
if (typeof onRejected !== 'function') {
onRejected = res => MockPromise.reject(res)
}

let promise2
if (this.status === 'resolve') {
promise2 = new MockPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onFufilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
if (this.status === 'reject') {
promise2 = new MockPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})

}
if (this.status === 'pending') {
promise2 = new MockPromise((resolve, reject) => {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
let x = onFufilled(this.value);
console.log(` onFufilled x pending`, x);
resolvePromise(promise2, x, resolve, reject)
})
})
this.onRejectedCallbacks.push(()=>{
setTimeout(() => {
let x = onRejected(this.reason)
console.log(` onRejected x pending`, x);
resolvePromise(promise2, x, resolve, reject)
})
})
})
}
return promise2
}

catch(onRejected) {
return this.then(null, onRejected)
}
finally(cb) {
const p = this.constructor
return this.then(
val => P.resolve(cb()).then(() => val),
reason = P.reject(cb()).then(() => {throw reason})
)
}
static resolve(val) {
return new MockPromise(function(resolve, reject) {
resolve(val)
})
}
static reject(reason) {
return new MockPromise(function(resolve, reject) {
reject(reason)
})
}
// 当数组中每个实例都成功时才会返回,返回的也是一个数组,每个参数为对应的promise返回的结果,如果有一项失败了,all方法都会返回失败
// 谁跑得慢以谁为准 如果有一个失败 则返回失败结果
static all(promiseList) {
return new MockPromise((resolve, reject) => {
let index = 0
const results = []
for (let i = 0; i < promiseList.length; i ++) {
const item = promiseList[i]
if (!item instanceof MockPromise) return
item.then(result => {
index ++
results[i] = result
if (index === promiseList.length) {
resolve(results)
}
}).catch(reason => reject(reason))
}
})
}
// Promise.all示例
// 谁跑得快 以谁为准
static race(promiseList) {
return new MockPromise(function(resolve, reject) {
promiseList.forEach((item) => {
if (!item instanceof MockPromise) return
item.then((val) => {
resolve(val)
}, (err) => {
reject(err)
})
})
})
}
}

/**
* @param {function} promise2
* @param {any} x
* @param {function} resolve reject 最外层的resolve reject
*/
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
reject(new TypeError('循环了'))
}
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let called
try {
let then = x.then
console.log(`x then`, then);
if (typeof then === 'function') {
// 第一个参数是将x这个promise方法作为this指向,后两个参数分别为成功失败回调
console.log(`called`, called);
then.call(x,
(
y => {
if (called) return
called = true
//因为可能promise中还有promise,所以需要递归
// this.resolvePromise(promise2, y, resolve, reject)
resolve(y)
},
err => {
if (called) return
called = true
reject(err)
}
)
)
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}

使用MockPromise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var p1 = MockPromise.resolve(1)
var p2 = MockPromise.resolve(p1)
var p3 = new MockPromise(function(resolve, reject) {
resolve('cpp MockPromise')
})
console.log(p1)
console.log(p2)
console.log(p1 === p1) // trye
p3.then(function(val) {
console.log(`p3: ${val} then1 ————`);
}).then(function(val) {
console.log(`${val} then3 ————`);
// then返回的mockPromise还是有问题!!循环引用
return MockPromise.reject('then is reject')
}).then(function(val) {
console.log(`${val} then4 ————`);
})

专业版 2

手写 cppPromise

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
170
171
172
173
174
175
// 专业版2
class myPromise {
constructor(fn) {
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = (val) => {
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = val
this.onResolvedCallbacks.forEach((cb) => {
setTimeout(() => {
cb(val)
}, 0)
})
}
}
const reject = (val) => {
if (this.status === 'pending') {
this.status = 'rejected'
this.reason = val;
this.onRejectedCallbacks.forEach((cb) => {
setTimeout(() => {
cb(val)
}, 0)
})
}
}
// 使用者传入的参数
try {
fn(resolve, reject)
} catch (e) {
reject(e)
}
}
// 构造器中resolve和reject的结果传入onFufilled和onRejected中
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v;
onRejected = typeof onRejected === 'function' ? onRejected : (e) => {throw e};
let promise2
if (this.status === 'fulfilled') {
promise2 = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
this.onResolvedCallbacks.push(() => {
const value = onFulfilled(this.value);
resolvePromise(promise2, value, resolve, reject)
})
} catch(e) {
reject(e)
}
}, 0)
})
}

if (this.status === 'rejected') {
promise2 = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
this.onRejectedCallbacks(() => {
const reason = onRejected(this.reason);
resolvePromise(promise2, reason, resolve, reject)
})
} catch(e) {
reject(e)
}
}, 0)
})
}
//
if (this.status === 'pending') {
promise2 = new myPromise((resolve, reject) => {
// 成功回调的收集
this.onResolvedCallbacks.push(() => {
const value = onFulfilled(this.value);
resolvePromise(promise2, value, resolve, reject)
})
// 失败回调的收集
this.onRejectedCallbacks(() => {
const reason = onRejected(this.reason);
resolvePromise(promise2, reason, resolve, reject)
})
})
}

return promise2
}
// 统一处理
resolvePromise(myPromise, val, resolve, reject) {
if (myPromise === val) {
return reject(new TypeError('循环引用'))
}
if (val && (typeof val === 'object' || typeof val === 'function')) {
try {
if (val instanceof myPromise) {
val.then(resolve)
} else {
resolve(val)
}
let thenFn = val.then
let called
if (typeof thenFn === 'function') {
thenFn.call(val, value => {
if (called) return
called = true
resolvePromise(promise2, value, resolve, reject)
}, err => {
if (called) return
called = true
reject(err)
})
// 其实就相当于
// if (val instanceof myPromise) {
// val.then(resolve, reject)
// } else {
// resolve(val)
// reject(val)
// }
} else {
resolve(val)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(val)
}
}
catch(onRejected) {
return this.then(null, onRejected)
}
}
myPromise.resolve = function(val) {
return new myPromise((resolve, reject) => {
resolve(val)
})
}
myPromise.reject = function(val) {
return new myPromise((resolve, reject) => {
reject(val)
})
}
// 入参是个由Promise实例组成的数组
// 返回值是个promise,因为可以使用.then
// 如果全部成功,状态变为resolved, 并且返回值组成一个数组传给回调
// 但凡有一个失败,状态变为rejected, 并将error返回给回调
myPromise.all = function(promises) {
return new myPromise((resolve, reject) => {
const result = []
let index = 0;
for(let item of promises) {
item.then((res) => {
result[index] = res
index ++
if (index === promises.length) {
resolve(result)
}
}, (err) => {
reject(err)
})
}
})
}

myPromise.race = function(promises) {
return new myPromise((resolve, reject) => {
for (let promise of promises) {
promise.then(resolve, reject)
}
})
}

专业版2 示例

1
2
3
4
5
6
7
8
9
10
// myPromise.all示例
let p1 = myPromise.resolve(1),
p2 = myPromise.resolve(2),
p3 = myPromise.resolve(3);

myPromise.all([p1, p2, p3]).then((res)=>{
console.log(res, 'res')
}, (err)=>{
console.log(err, 'err')
})

参考链接