# 6.根据 promiseA+实现一个自己的 promise
# 手写 promise 思路
- 因为 promise 传入的是一个函数,所以要在里面执行器立即执行 excutor(resolve,reject),执行器函数是同步执行
- 定义 resolve 和 reject 函数
- resolve 和 reject 是异步函数,将回调放入 callbacks 队列。(判断队列长度是否为 0,不为零的话,外层套一个 setTimeout,执行成功的回调)
- 回调队列里面是{onResolve(){},onReject(){}}这样的数组对象,所以在 forEach 的时候要调用 onResolve/onReject 函数
- 因为执行器有可能会抛出异常,所以对 excutor 执行器套一层 try,catch。
- 在调用 resove()函数的时候,他的 this,是直接调用的,指向 window,所以可以把 this 存起来。
- then 方法同步执行,then 里面的参数异步回调。也就是说先把 then 里面的方法定义了,等遇到 resolve()的时候才调用
选自:Promise 不会??看这里!!!史上最通俗易懂的 Promise!!! (opens new window) @[TOC]
# 步骤一:实现成功和失败的回调方法
要实现上面代码中的功能,也是 promise 最基本的功能。首先,需要创建一个构造函数 promise,创建一个 promisel 类,在使用的时候传入了一个执行器 executor,executor 会传入两个参数:成功(resolve)和失败(reject)。之前说过,只要成功,就不会失败,只要失败就不会成功。所以,默认状态下,在调用成功时,就返回成功态,调用失败时,返回失败态。代码如下:
//声明 class
class myPromise {
//声明构造方法
constructor(executor) {
--------------------------------------------准备工作
const self = this;
//声明属性
self.promiseStatus = 'pending';
self.promiseValue = '';
self.callbacks = [];
--------------------------------------------主要代码
//声明函数 resolve
function resolve(data) {
//状态修改唯一性
if (self.promiseStatus !== 'pending') return;
// resolve 修改 Promise 对象状态(promiseStatus)为成功, 设置其成功的值(promiseValue)
//修改状态
self.promiseStatus = 'resolved';
//修改值
self.promiseValue = data;
//执行成功的回调
setTimeout(() => {
if (self.callbacks.length > 0) {
self.callbacks.forEach(callbackObj => {
callbackObj.onResolved(self.promiseValue);
});
}
})
}
//声明函数 reject
function reject(data) {
//如果状态修改过, 则直接返回
if (self.promiseStatus !== 'pending') return;
//修改状态
self.promiseStatus = 'rejected';
//修改值
self.promiseValue = data;
//执行失败的回调
setTimeout(() => {
if (self.callbacks.length > 0) {
self.callbacks.forEach(callbackObj => {
callbackObj.onRejected(self.promiseValue);
});
}
});
}
------------------------------------------执行函数
/**上面是定义resolve和reject函数,命名无所谓。下面的try才是执行函数*/
try {
executor(resolve, reject);
} catch (e) {
//如果抛错 则修改 promise 对象状态为失败
reject(e);
}
}
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
promise A+规范规定,在有异常错误时,则执行失败函数。
举例:
<div>开始异步请求</div>;
//声明 class
class myPromise {
//声明构造方法
constructor(executor) {
const self = this;
//声明属性
self.promiseStatus = "pending";
self.promiseValue = "";
self.callbacks = [];
//声明函数 resolve
function resolve(data) {
//状态修改唯一性
if (self.promiseStatus !== "pending") return;
// resolve 修改 Promise 对象状态(promiseStatus)为成功, 设置其成功的值(promiseValue)
//修改状态
self.promiseStatus = "resolved";
//修改值
self.promiseValue = data;
//执行成功的回调
setTimeout(() => {
if (self.callbacks.length > 0) {
self.callbacks.forEach((callbackObj) => {
callbackObj.onResolved(self.promiseValue);
});
}
});
}
//声明函数 reject
function reject(data) {
//如果状态修改过, 则直接返回
if (self.promiseStatus !== "pending") return;
//修改状态
self.promiseStatus = "rejected";
//修改值
self.promiseValue = data;
//执行失败的回调
setTimeout(() => {
if (self.callbacks.length > 0) {
self.callbacks.forEach((callbackObj) => {
callbackObj.onRejected(self.promiseValue);
});
}
});
}
//执行『执行器函数』
try {
executor(resolve, reject);
} catch (e) {
//如果抛错 则修改 promise 对象状态为失败
reject(e);
}
}
}
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
# 步骤二:then 方法链式调用
then 方法是 promise 的最基本的方法,返回的是两个回调,一个成功的回调,一个失败的回调,实现过程如下:
//声明 then 方法
then(onResolved, onRejected) {
//默认值设置
if (onRejected === undefined) {
onRejected = reason => {
throw reason
};
}
if (onResolved === undefined) {
onResolved = value => value;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
为了实现这样的效果,则上一次的代码将要重新写过,我们可以把每次调用 resolve 的结果存入一个数组中,每次调用 reject 的结果存入一个数组。这就是 为何会在上面定义两个数组,且分别在 resolve()和 reject()遍历两个数组的原因。因此,在调用 resolve()或者 reject()之前,我们在 pending 状态时,会把多次 then 中的结果存入数组中,则上面的代码会改变为:
//声明 then 方法
then(onResolved, onRejected) {
//默认值设置
if (onRejected === undefined) {
onRejected = reason => {
throw reason
};
}
if (onResolved === undefined) {
onResolved = value => value;
}
return new Promise((resolve, reject) => {
//封装函数
let callback = (type) => {
//如果函数执行抛出错误
try {
//获取回调的执行结果
let result = type(this.promiseValue);
//判断
if (result instanceof Promise) {
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
//状态为成功
resolve(result);
}
} catch (e) {
//如果回调抛出错误, 则修改 promise 对象状态为失败
reject(e);
}
}
//判断 promise 对象的状态
//成功的状态
if (this.promiseStatus === 'resolved') {
setTimeout(() => {
callback(onResolved);
});
}
//失败的状态
if (this.promiseStatus === 'rejected') {
setTimeout(() => {
callback(onRejected);
})
}
//pending状态
if (this.promiseStatus === 'pending') {
//保存回调函数
this.callbacks.push({
onResolved: () => {
callback(onResolved);
},
onRejected: () => {
callback(onRejected);
}
});
}
})
}
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
Promise A+规范中规定 then 方法可以链式调用
在 promise 中,要实现链式调用返回的结果是返回一个新的 promise,第一次 then 中返回的结果,无论是成功或失败,都将返回到下一次 then 中的成功态中,但在第一次 then 中如果抛出异常错误,则将返回到下一次 then 中的失败态中
根据 promise A+规范原理,promise 在自己的框架中,封装了一系列的内置的方法。
- 捕获错误的方法 catch()
- 解析全部方法 all()
- 竞赛 race()
- 生成一个成功的 promise resolve()
- 生成一个失败的 promise reject()
# 最终代码和测试
# ES6.Class 实现
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
this.reason = null;
this.resolveCallbacks = [];
this.rejectCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.status === PENDING) {
this.value = value;
this.status = RESOLVED;
this.resolveCallbacks.forEach((onFulfilled) => {
onFulfilled();
});
}
}
reject(reason) {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
this.rejectCallbacks.forEach((onRejected) => {
onRejected();
});
}
}
then(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (data) => data;
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err;
};
let promise2 = new Promise((resolve, reject) => {
if (this.status === PENDING) {
this.resolveCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(x, promise2, resolve, reject);
} catch (error) {
reject(error);
}
});
});
this.rejectCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(x, promise2, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if (this.status === RESOLVED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(x, promise2, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(x, promise2, resolve, reject);
} catch (error) {
reject(error);
}
});
}
});
return promise2;
}
}
function resolvePromise(x, promise2, resolve, reject) {
if (x === promise2) {
return reject(new TypeError("Chaining cycle detected for promise!"));
}
if (x && (typeof x === "object" || typeof x === "function")) {
let called;
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
(value) => {
if (called) return;
called = true;
resolvePromise(value, promise2, resolve, reject);
},
(reason) => {
if (called) return;
called = true;
reject(reason);
}
);
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
Promise.deferred = function () {
let deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
};
var promisesAplusTests = require("promises-aplus-tests");
promisesAplusTests(Promise, function (err) {
// All done; output is in the console. Or check `err` for number of failures.
console.log("测试用例失败", err);
});
/*
Promise.resolve()
Promise.reject()
Promise.all([])
Promise.race()
Promise.allSettled([])
...
*/
module.exports = Promise;
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
# ES5 实现
//声明 class
class Promise {
//声明构造方法
constructor(executor) {
const self = this;
//声明属性
self.promiseStatus = "pending";
self.promiseValue = "";
self.callbacks = [];
//声明函数 resolve
function resolve(data) {
//状态修改唯一性
if (self.promiseStatus !== "pending") return;
// resolve 修改 Promise 对象状态(promiseStatus)为成功, 设置其成功的值(promiseValue)
//修改状态
self.promiseStatus = "resolved";
//修改值
self.promiseValue = data;
//执行成功的回调
setTimeout(() => {
if (self.callbacks.length > 0) {
self.callbacks.forEach((callbackObj) => {
callbackObj.onResolved(self.promiseValue);
});
}
});
}
//声明函数 reject
function reject(data) {
//如果状态修改过, 则直接返回
if (self.promiseStatus !== "pending") return;
//修改状态
self.promiseStatus = "rejected";
//修改值
self.promiseValue = data;
//执行失败的回调
setTimeout(() => {
if (self.callbacks.length > 0) {
self.callbacks.forEach((callbackObj) => {
callbackObj.onRejected(self.promiseValue);
});
}
});
}
//执行『执行器函数』
try {
executor(resolve, reject);
} catch (e) {
//如果抛错 则修改 promise 对象状态为失败
reject(e);
}
}
//声明 then 方法
then(onResolved, onRejected) {
//默认值设置
if (onRejected === undefined) {
onRejected = (reason) => {
throw reason;
};
}
if (onResolved === undefined) {
onResolved = (value) => value;
}
return new Promise((resolve, reject) => {
//封装函数
let callback = (type) => {
//如果函数执行抛出错误
try {
//获取回调的执行结果
let result = type(this.promiseValue);
//判断
if (result instanceof Promise) {
result.then(
(v) => {
resolve(v);
},
(r) => {
reject(r);
}
);
} else {
//状态为成功
resolve(result);
}
} catch (e) {
//如果回调抛出错误, 则修改 promise 对象状态为失败
reject(e);
}
};
//判断 promise 对象的状态
//成功的状态
if (this.promiseStatus === "resolved") {
setTimeout(() => {
callback(onResolved);
});
}
//失败的状态
if (this.promiseStatus === "rejected") {
setTimeout(() => {
callback(onRejected);
});
}
//pending状态
if (this.promiseStatus === "pending") {
//保存回调函数
this.callbacks.push({
onResolved: () => {
callback(onResolved);
},
onRejected: () => {
callback(onRejected);
},
});
}
});
}
//声明 catch 方法
catch(onRejected) {
return this.then(undefined, onRejected);
}
//声明 resolve 静态方法
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(
(v) => {
resolve(v);
},
(r) => {
reject(r);
}
);
} else {
resolve(value);
}
});
}
//声明 reject 静态方法
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
//声明 all 静态方法
static all(promisesArr) {
//声明数组存放成功的值
const resultArr = [];
//计数器
let count = 0;
//设置promise结构
return new Promise((resolve, reject) => {
//resolve 和 reject 调用的时机 ****
for (let i = 0; i < promisesArr.length; i++) {
//获取当前正在遍历的 promise 对象
promisesArr[i].then(
(value) => {
//将当前成功的 promise 的值 存入到数组中
// resultArr.push(value);// 此方法不可取
resultArr[i] = value;
//计数器加一
count++;
//判断结果数组的长度 ['ok', undefined, 'Yeah!'].length ==3 count 2
// ['OK','Success','Year'] count === 3 是所有 promise 成功的标志
if (count === promisesArr.length) {
//设置状态为成功
resolve(resultArr);
}
},
(reason) => {
//如果有一个 promise 失败, 则 all 返回的状态为失败
reject(reason);
}
);
}
});
}
//声明 race 静态方法
static race(promisesArr) {
return new Promise((resolve, reject) => {
// resolve reject 函数
//遍历 标识符
promisesArr.forEach((promise) => {
promise.then(
(value) => {
//如果 promise 对象成功, 则修改返回的 promise 对象状态为成功
resolve(value);
},
(reason) => {
//如果 promise 对象失败, 则修改返回的 promise 对象状态为失败
reject(reason);
}
);
});
});
}
}
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207