logo

搞一个基于Promise/A+规范的Promise

RT,搞一个基于 Promise/A+规范的 Promise。

Promise/A+ 规范

规范简述,详细规范可参见见【翻译】Promises/A+规范

  1. Promise 包含 pending,fulfilled,rejected 三个状态。
  • pending 可以转换为 fulfilled,rejected 状态。
  • fulfilled,rejected 状态不可变
  1. Promise 必须提供 then 方法。
  • then 方法接受两个参数,分别对应 pending 转换为 fulfilled,rejected 状态的回调(onFulfilled,onRejected)
  • then 方法返回一个新的 Promise
  1. Promise解决过程,onFulfilled,onRejected返回值为x,返回的为promise2
  • x 与 promise2 相等返回TypeError
  • x为thenable的对象或函数,以x为作用域调用其then方法
  • x不为thenable的对象与函数,执行promise2

整啊,搞啊,弄啊

构造函数

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
function PromiseX(executor) {
let that = this;
/* 状态 */
that.status = "pending";
/* 值 */
that.value = void 0;
/* 存储onFulfilled回调 */
that.fulfilledCallbacks = [];
/* 存储onRejected回调 */
that.rejectedCallbacks = [];

/* resolve方法:
- 执行PromiseX状态变换时的fulfilledCallbacks
- 转换当前Promise状态为fulfilled
- 将当前PromiseX的终值设置为传入值
*/
let resolve = function(value) {
/* 只有pending状态的Promise才能变换状态 */
if (that.status === "pending") {
that.status = "resolved";
that.value = value;
that.fulfilledCallbacks.forEach(function(fn) {
fn(that.value);
});
}
};
let reject = function(value) {
if (that.status === "pending") {
that.status = "rejected";
that.value = value;
that.rejectedCallbacks.forEach(function(fn) {
fn(that.value);
});
}
};
/* 捕获异常 */
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}

reslovePromise

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
/**
*如果relove,reject一个thenable(拥有then方法的)对象(不仅限于PromiseX)则调用该对象上thenable方法
*
* @param {PromiseX} promise2 返回的promise2
* @param {*} x OnFulfilled返回值
* @param {*} resolve 当前PromiseX的resolve,reject方法
* @param {*} reject
* @returns
*/
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
/* 返回TypeError */
return reject(new TypeError("can't return self"));
}

/* then方法是否被调用的标识,防止调用多次 */
let hasThenCalled;

/* 终值为thenable对象,调用其then方法 */
if (x !== null && (typeof x === "function" || typeof x === "object")) {
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
function(y) {
if (hasThenCalled) return;
hasThenCalled = true;
resolvePromise(promise2, y, resolve, reject);
},
function(e) {
if (hasThenCalled) return;
hasThenCalled = true;
reject(e);
}
);
} else {
resolve(x);
}
} catch (e) {
if (hasThenCalled) return;
hasThenCalled = true;
reject(e);
}
} else {
resolve(x);
}
}

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
PromiseX.prototype.then = function(onFulfilled, onRejected) {
/* then方法返回一个新的Promise */
let promise2,
that = this;

/*
onFulfilled,onRejected忽略非函数类型 ,
非函数类型直接返回传入值方便值的传递
*/
onFulfilled =
typeof onFulfilled === "function"
? onFulfilled
: function(x) {
return x;
};
onRejected =
typeof onRejected === "function"
? onRejected
: function(e) {
throw e;
};

/* pending表示状态还未改变 */
if (that.status === "pending") {
promise2 = new PromiseX(function(resolve, reject) {
/* 将回调存入上一个promise的fulfilledCallbacks/rejectedCallbacks */
that.fulfilledCallbacks.push(function() {
/* promise onFulfilled 函数在下一轮事件循环中执行 */
setTimeout(function() {
try {
let res = onFulfilled(that.value);
/* 当返回值为thenable对象时,当前PromiseX的状态取决于返回PromiseX */
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
that.rejectedCallbacks.push(function() {
setTimeout(function() {
try {
let res = onRejected(that.value);
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
});
} else if (that.status === "resolved") {
promise2 = new PromiseX(function(resolve, reject) {
setTimeout(function() {
try {
let res = onFulfilled(that.value);
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
} else if (that.status === "rejected") {
promise2 = new PromiseX(function(resolve, reject) {
setTimeout(function() {
try {
let res = onRejected(that.value);
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
return promise2;
};

测试一哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 测试
* npm i -g promises-aplus-tests
* promises-aplus-tests test.js
*/

PromiseX.deferred = function() {
let obj = {};
obj.promise = new PromiseX(function(resolve, reject) {
obj.resolve = resolve;
obj.reject = reject;
});
return obj;
};

module.exports = PromiseX;

拓展一哈

PromiseX.prototype.catch()

1
2
3
PromiseX.prototype.catch = function(onRejected){
return this.then(null,onRejected)
}

PromiseX.resolve()

1
2
3
4
5
PromiseX.resolve = function(value){
return new PromiseX(reslove=>{
reslove(value)
})
}

PromiseX.reject()

1
2
3
4
5
PromiseX.reject = function(reason){
return new PromiseX((reslove,reject)=>{
reject(reason)
})
}

PromiseX.all()

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
/**
*
*
* @param {array} promises
* @returns {arrya} values
*/
PromiseX.all = function(promises) {
let resloveAll;
let values = [];
let count = 0;
let pushValue = (index,value)=>{
values[index] = value
if(count === length - 1){
resloveAll(values)
}
}
return new PromiseX(function(resolve, reject) {
resloveAll = resolve
promises.forEach((promise,index)=>{
promise.then(value=>{
pushValue(index,value)
})
})
});
};

PromiseX.race()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
*
*
* @param {array} promises
* @returns {*} value
*/

PromiseX.race = function(promises){
return new PromiseX((resolve,reject)=>{
promises.forEach((promise,index)=>{
promise.then(reslove,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
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
function PromiseX(executor) {
let that = this;
/* 状态 */
that.status = "pending";
/* 值 */
that.value = void 0;
/* 存储onFulfilled回调 */
that.fulfilledCallbacks = [];
/* 存储onRejected回调 */
that.rejectedCallbacks = [];

/* resolve方法:
- 执行PromiseX状态变换时的fulfilledCallbacks
- 转换当前Promise状态为fulfilled
- 将当前PromiseX的终值设置为传入值
*/
let resolve = function(value) {
/* 只有pending状态的Promise才能变换状态 */
if (that.status === "pending") {
that.status = "resolved";
that.value = value;
that.fulfilledCallbacks.forEach(function(fn) {
fn(that.value);
});
}
};
let reject = function(value) {
if (that.status === "pending") {
that.status = "rejected";
that.value = value;
that.rejectedCallbacks.forEach(function(fn) {
fn(that.value);
});
}
};
/* 捕获异常 */
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}

/**
*如果relove,reject一个thenable(拥有then方法的)对象(不仅限于PromiseX)则调用该对象上thenable方法
*
* @param {PromiseX} promise2 返回的promise2
* @param {*} x OnFulfilled返回值
* @param {*} resolve 当前PromiseX的resolve,reject方法
* @param {*} reject
* @returns
*/
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
/* 返回TypeError */
return reject(new TypeError("can't return self"));
}

/* then方法是否被调用的标识,防止调用多次 */
let hasThenCalled;

/* 终值为thenable对象,调用其then方法 */
if (x !== null && (typeof x === "function" || typeof x === "object")) {
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
function(y) {
if (hasThenCalled) return;
hasThenCalled = true;
resolvePromise(promise2, y, resolve, reject);
},
function(e) {
if (hasThenCalled) return;
hasThenCalled = true;
reject(e);
}
);
} else {
resolve(x);
}
} catch (e) {
if (hasThenCalled) return;
hasThenCalled = true;
reject(e);
}
} else {
resolve(x);
}
}

PromiseX.prototype.then = function(onFulfilled, onRejected) {
/* then方法返回一个新的Promise */
let promise2,
that = this;

/*
onFulfilled,onRejected忽略非函数类型 ,
非函数类型直接返回传入值方便值的传递
*/
onFulfilled =
typeof onFulfilled === "function"
? onFulfilled
: function(x) {
return x;
};
onRejected =
typeof onRejected === "function"
? onRejected
: function(e) {
throw e;
};

/* pending表示状态还未改变 */
if (that.status === "pending") {
promise2 = new PromiseX(function(resolve, reject) {
/* 将回调存入上一个promise的fulfilledCallbacks/rejectedCallbacks */
that.fulfilledCallbacks.push(function() {
/* promise onFulfilled 函数在下一轮事件循环中执行 */
setTimeout(function() {
try {
let res = onFulfilled(that.value);
/* 当返回值为thenable对象时,当前PromiseX的状态取决于返回PromiseX */
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
that.rejectedCallbacks.push(function() {
setTimeout(function() {
try {
let res = onRejected(that.value);
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
});
} else if (that.status === "resolved") {
promise2 = new PromiseX(function(resolve, reject) {
setTimeout(function() {
try {
let res = onFulfilled(that.value);
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
} else if (that.status === "rejected") {
promise2 = new PromiseX(function(resolve, reject) {
setTimeout(function() {
try {
let res = onRejected(that.value);
resolvePromise(promise2, res, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
return promise2;
};

PromiseX.prototype.catch = function(onRejected){
return this.then(null,onRejected)
}

PromiseX.resolve = function(value){
return new PromiseX(reslove=>{
reslove(value)
})
}

PromiseX.reject = function(reason){
return new PromiseX((reslove,reject)=>{
reject(reason)
})
}

/**
*
*
* @param {array} promises
* @returns {arrya} values
*/
PromiseX.all = function(promises) {
let resloveAll;
let values = [];
let count = 0;
let pushValue = (index,value)=>{
values[index] = value
if(count === length - 1){
resloveAll(values)
}
}
return new PromiseX(function(resolve, reject) {
resloveAll = resolve
promises.forEach((promise,index)=>{
promise.then(value=>{
pushValue(index,value)
})
})
});
};

/**
*
*
* @param {array} promises
* @returns {*} value
*/

PromiseX.race = function(promises){
return new PromiseX((resolve,reject)=>{
promises.forEach((promise,index)=>{
promise.then(reslove,reject)
})
})
}




/**
* 测试
* npm i -g promises-aplus-tests
* promises-aplus-tests test.js
*/

PromiseX.deferred = function() {
let obj = {};
obj.promise = new PromiseX(function(resolve, reject) {
obj.resolve = resolve;
obj.reject = reject;
});
return obj;
};

module.exports = PromiseX;

参考链接

【翻译】Promises/A+规范

Tags: Promise