-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtest_my_promise.js
223 lines (213 loc) · 10.8 KB
/
test_my_promise.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
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
class myPromise {
// 为了统一用static创建静态属性,用来管理状态
static PENDING = 'pending';
static FULFILLED = 'fulfilled';
static REJECTED = 'rejected';
// 构造函数:通过new命令生成对象实例时,自动调用类的构造函数
constructor(func) { // 给类的构造方法constructor添加一个参数func
this.PromiseState = myPromise.PENDING; // 指定Promise对象的状态属性 PromiseState,初始值为pending
this.PromiseResult = null; // 指定Promise对象的结果 PromiseResult
this.onFulfilledCallbacks = []; // 保存成功回调
this.onRejectedCallbacks = []; // 保存失败回调
try {
/**
* func()传入resolve和reject,
* resolve()和reject()方法在外部调用,这里需要用bind修正一下this指向
* new 对象实例时,自动执行func()
*/
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
// 生成实例时(执行resolve和reject),如果报错,就把错误信息传入给reject()方法,并且直接执行reject()方法
this.reject(error)
}
}
resolve(result) { // result为成功态时接收的终值
// 只能由pedning状态 => fulfilled状态 (避免调用多次resolve reject)
if (this.PromiseState === myPromise.PENDING) {
/**
* 为什么resolve和reject要加setTimeout?
* 2.2.4规范 onFulfilled 和 onRejected 只允许在 execution context 栈仅包含平台代码时运行.
* 注1 这里的平台代码指的是引擎、环境以及 promise 的实施代码。实践中要确保 onFulfilled 和 onRejected 方法异步执行,且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。
* 这个事件队列可以采用“宏任务(macro-task)”机制,比如setTimeout 或者 setImmediate; 也可以采用“微任务(micro-task)”机制来实现, 比如 MutationObserver 或者process.nextTick。
*/
setTimeout(() => {
this.PromiseState = myPromise.FULFILLED;
this.PromiseResult = result;
/**
* 在执行resolve或者reject的时候,遍历自身的callbacks数组,
* 看看数组里面有没有then那边 保留 过来的 待执行函数,
* 然后逐个执行数组里面的函数,执行的时候会传入相应的参数
*/
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
});
}
}
reject(reason) { // reason为拒绝态时接收的终值
// 只能由pedning状态 => rejected状态 (避免调用多次resolve reject)
if (this.PromiseState === myPromise.PENDING) {
setTimeout(() => {
this.PromiseState = myPromise.REJECTED;
this.PromiseResult = reason;
this.onRejectedCallbacks.forEach(callback => {
callback(reason)
})
});
}
}
/**
* [注册fulfilled状态/rejected状态对应的回调函数]
* @param {function} onFulfilled fulfilled状态时 执行的函数
* @param {function} onRejected rejected状态时 执行的函数
* @returns {function} newPromsie 返回一个新的promise对象
*/
then(onFulfilled, onRejected) {
/**
* 参数校验:Promise规定then方法里面的两个参数如果不是函数的话就要被忽略
* 所谓“忽略”并不是什么都不干,
* 对于onFulfilled来说“忽略”就是将value原封不动的返回,
* 对于onRejected来说就是返回reason,
* onRejected因为是错误分支,我们返回reason应该throw一个Error
*/
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason;
};
// 2.2.7规范 then 方法必须返回一个 promise 对象
let promise2 = new myPromise((resolve, reject) => {
if (this.PromiseState === myPromise.FULFILLED) {
/**
* 为什么这里要加定时器setTimeout?
* 2.2.4规范 onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用 注1
* 这里的平台代码指的是引擎、环境以及 promise 的实施代码。
* 实践中要确保 onFulfilled 和 onRejected 方法异步执行,且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。
* 这个事件队列可以采用“宏任务(macro-task)”机制,比如setTimeout 或者 setImmediate; 也可以采用“微任务(micro-task)”机制来实现, 比如 MutationObserver 或者process.nextTick。
*/
setTimeout(() => {
try {
// 2.2.7.1规范 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x),即运行resolvePromise()
let x = onFulfilled(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 2.2.7.2 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
reject(e); // 捕获前面onFulfilled中抛出的异常
}
});
} else if (this.PromiseState === myPromise.REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
});
} else if (this.PromiseState === myPromise.PENDING) {
// pending 状态保存的 resolve() 和 reject() 回调也要符合 2.2.7.1 和 2.2.7.2 规范
this.onFulfilledCallbacks.push(() => {
try {
let x = onFulfilled(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e);
}
});
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
})
return promise2
}
}
/**
* 对resolve()、reject() 进行改造增强 针对resolve()和reject()中不同值情况 进行处理
* @param {promise} promise2 promise1.then方法返回的新的promise对象
* @param {[type]} x promise1中onFulfilled或onRejected的返回值
* @param {[type]} resolve promise2的resolve方法
* @param {[type]} reject promise2的reject方法
*/
function resolvePromise(promise2, x, resolve, reject) {
// 2.3.1规范 如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 2.3.2规范 如果 x 为 Promise ,则使 promise2 接受 x 的状态
if (x instanceof myPromise) {
if (x.PromiseState === myPromise.PENDING) {
/**
* 2.3.2.1 如果 x 处于等待态, promise 需保持为等待态直至 x 被执行或拒绝
* 注意"直至 x 被执行或拒绝"这句话,
* 这句话的意思是:x 被执行x,如果执行的时候拿到一个y,还要继续解析y
*/
x.then(y => {
resolvePromise(promise2, y, resolve, reject)
}, reject);
} else if (x.PromiseState === myPromise.FULFILLED) {
// 2.3.2.2 如果 x 处于执行态,用相同的值执行 promise
resolve(x.PromiseResult);
} else if (x.PromiseState === myPromise.REJECTED) {
// 2.3.2.3 如果 x 处于拒绝态,用相同的据因拒绝 promise
reject(x.PromiseResult);
}
} else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
// 2.3.3 如果 x 为对象或函数
try {
// 2.3.3.1 把 x.then 赋值给 then
var then = x.then;
} catch (e) {
// 2.3.3.2 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
return reject(e);
}
/**
* 2.3.3.3
* 如果 then 是函数,将 x 作为函数的作用域 this 调用之。
* 传递两个回调函数作为参数,
* 第一个参数叫做 `resolvePromise` ,第二个参数叫做 `rejectPromise`
*/
if (typeof then === 'function') {
// 2.3.3.3.3 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
let called = false; // 避免多次调用
try {
then.call(
x,
// 2.3.3.3.1 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
// 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
r => {
if (called) return;
called = true;
reject(r);
}
)
} catch (e) {
/**
* 2.3.3.3.4 如果调用 then 方法抛出了异常 e
* 2.3.3.3.4.1 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
*/
if (called) return;
called = true;
/**
* 2.3.3.3.4.2 否则以 e 为据因拒绝 promise
*/
reject(e);
}
} else {
// 2.3.3.4 如果 then 不是函数,以 x 为参数执行 promise
resolve(x);
}
} else {
// 2.3.4 如果 x 不为对象或者函数,以 x 为参数执行 promise
return resolve(x);
}
}