-
Notifications
You must be signed in to change notification settings - Fork 0
/
PromiseMy.js
157 lines (142 loc) · 4.53 KB
/
PromiseMy.js
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
/*
一个简单的promise实现
思路:
1.首先执行传入的函数,并传入两个函数作为参数,第一个函数把 resolve 函数的参数压入队列,并调用resolve函数
第二个函数把 reject 函数的参数压入相应队列,并调用resolve函数(这里参数压入队列的作用是方便同步Promise时
then 方法直接执行回调函数)。
2.在 resolve 中把状态变为 RESOLVE,并按序取出在 then 中存入队列的 RESOLVE 态的回调函数及传入的参数进行执行
reject 同上
3.在 then 方法中先查看状态,若是 RESOLVE 则直接执行回调函数(同步Promise),否则把回调函数压入队列。
*/
class PromiseMy {
constructor(fun) {
this.STATUS = {
PENDING: 0,
RESOLVE: 1,
REJECT: 2
}
this.succArgs = undefined;
this.failArgs = undefined;
this.succCbs = [];
this.failCbs = [];
this._status = this.STATUS.PENDING;
this._execFun(fun);
}
_execFun(fun) {
const that = this;
if(this._isFun(fun)) {
/*这里不能使用箭头函数,不然取不到arguments*/
fun(function() {
that.succArgs = [].slice.apply(arguments);
that.resolve.apply(that ,arguments);
},function() {
that.failArgs = [].slice.apply(arguments);
that.reject.apply(that, arguments);
})
}else {
setTimeout(() => {
that.resolve(fun);
})
}
}
_isFun(fun) {
return Object.prototype.toString.call(fun) === '[object Function]';
}
resolve() {
this._status = this.STATUS.RESOLVE;
let ret,
callBack = this.succCbs.shift();
if(this._isFun(callBack)) {
ret = callBack.apply(callBack, arguments);
if (!(ret instanceof PromiseMy)) {
let _ret = ret;
ret = new PromiseMy((resolve, reject) => {
setTimeout(() => {
resolve(_ret);
});
});
}
ret.succCbs = this.succCbs.slice();
}
}
reject() {
this._status = this.STATUS.REJECT;
var ret,
args = arguments,
callBack = this.failCbs.shift();
if(this._isFun(callBack)) {
ret = callBack.apply(callBack, args);
if (!(ret instanceof PromiseMy)) {
var _ret = ret;
ret = new PromiseMy((resolve, reject) => {
setTimeout(() => {
reject(_ret);
});
});
}
ret.failCbs = this.failCbs.slice();
}
}
then(succCb, failCb) {
if (succCb) {
if(this._status === this.STATUS.RESOLVE) {/*同步Promise时会直接在这调用回调*/
succCb.apply(succCb, this.succArgs);
}else {
this.succCbs.push(succCb);
}
}
if(failCb) {
if(this._status === this.STATUS.REJECT) {/*同步Promise时会直接在这调用回调*/
failCbs.apply(failCbs, this.failArgs);
}else {
this.failCbs.push(failCb);
}
}
return this;
}
catch(failCb) {
if(failCb) {
if(this._status === this.STATUS.REJECT) {/*同步Promise时会直接在这调用回调*/
failCbs.apply(failCbs, this.failArgs);
}else {
this.failCbs.push(failCb);
}
}
return this;
}
}
let a = new PromiseMy((resolve, reject) => {
setTimeout(() => {
resolve(' first');
}, 200)
})
a.then(function (e) {
console.log(e)
return 'second'
}).then(function (e) {
console.log(e)
return 'thrid'
}).then(function (e) {
console.log(e)
}).catch(function(e) {
console.log(e)
return 55
})
let b = new PromiseMy((resolve, reject) => {
setTimeout(() => {
reject(' fail');
}, 300)
})
b.then(function (e) {
console.log(e)
return 'second'
}).then(function (e) {
console.log(e)
return 'thrid'
}).then(function (e) {
console.log(e)
}).catch(function(e) {
console.log(e)
})
let c = new PromiseMy('not function')
c.then((e) => console.log(e))