Repository navigation
Expand file tree
/
Copy pathmyPromiseNotes.js
More file actions
226 lines (215 loc) · 10.3 KB
/
Copy pathmyPromiseNotes.js
File metadata and controls
226 lines (215 loc) · 10.3 KB
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
/**
* 手写 Promise 核心原理,完整的 Promise/A+ 实现,通过了 Promise/A+ 官方872个测试用例测试
* 按步分析 注释加持版
*/
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为成功态时接收的终值
// 只能由pending状态 => fulfilled状态 (避免调用多次resolve reject)
if (this.PromiseState === myPromise.PENDING) {
this.PromiseState = myPromise.FULFILLED;
this.PromiseResult = result;
/**
* 在执行resolve或者reject的时候,遍历自身的callbacks数组,
* 看看数组里面有没有then那边 保留 过来的 待执行函数,
* 然后逐个执行数组里面的函数,执行的时候会传入相应的参数
*/
this.onFulfilledCallbacks.forEach(callback => {
callback(result)
})
}
}
reject(reason) { // reason为拒绝态时接收的终值
// 只能由pending状态 => rejected状态 (避免调用多次resolve reject)
if (this.PromiseState === myPromise.PENDING) {
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) {
// 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 {
if (typeof onFulfilled !== 'function') {
// 2.2.7.3规范 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
resolve(this.PromiseResult);
} else {
// 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 {
if (typeof onRejected !== 'function') {
// 2.2.7.4规范 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因
reject(this.PromiseResult);
} else {
let x = onRejected(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
reject(e)
}
});
} else if (this.PromiseState === myPromise.PENDING) {
// pending 状态保存的 onFulfilled() 和 onRejected() 回调也要符合 2.2.7.1,2.2.7.2,2.2.7.3 和 2.2.7.4 规范
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
if (typeof onFulfilled !== 'function') {
resolve(this.PromiseResult);
} else {
let x = onFulfilled(this.PromiseResult);
resolvePromise(promise2, x, resolve, reject);
}
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
if (typeof onRejected !== 'function') {
reject(this.PromiseResult);
} else {
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) {
throw new TypeError('Chaining cycle detected for promise');
}
if (x instanceof myPromise) {
/**
* 2.3.2 如果 x 为 Promise ,则使 promise2 接受 x 的状态
* 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y
*/
x.then(y => {
resolvePromise(promise2, y, resolve, reject)
}, reject);
} 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);
}
}
myPromise.deferred = function () {
let result = {};
result.promise = new myPromise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
module.exports = myPromise;