1 /*
2 尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
3 */
4
5
6 // 定义三个状态
7 const PENDING = "PENDING";
8 const RESOLVED = "RESOLVED";
9 const REJECTED = 'REJECTED';
10 function resolvePromise(x, promise2, resolve, reject) {
11 //判断x === promise, 抛出类型错误
12 if (x === promise2) {
13 console.log('======')
14 return reject(new TypeError('类型错误'))
15 }
16 // 允许状态改变一次
17 let called = false;
18
19
20
21 try {
22 //判断x是否包含then属性,thenable
23 if (typeof x === 'object' && x !== null) {
24 const then = x.then;
25 if (typeof then === "function") {
26 // console.log(typeof then)
27 then.call(x, v => {
28 if (called) return;
29 called = true;
30 resolvePromise(v, promise2, resolve, reject)
31 }, r => {
32 if (called) return;
33 called = true;
34 reject(r)
35 })
36 } else {
37 if (called) return;
38 called = true;
39 resolve(x)
40 }
41 } else {
42 if (called) return;
43 called = true;
44 resolve(x)
45 }
46 } catch (e) {
47 if (called) return;
48 called = true;
49 reject(e)
50 }
51 }
52 class Promise {
53 constructor(exectuor) {
54 try {
55 //捕获执行器错误
56 exectuor(this.resolve, this.reject)
57 } catch (e) {
58 this.reject(e)
59 }
60 }
61
62 status = PENDING;
63 value = null;
64 reason = null;
65 //存储失败和成功的回调
66 onFullFilledCallbacks = [];
67 onRejectedCallbacks = [];
68
69 static all (args) {
70 return new Promise((resolve, reject) => {
71 args.reduce((prev, curr, i, arr) => {
72 if (curr instanceof Promise) {
73 curr.then((v) => {
74 prev[i] = v;
75 if (prev.length === arr.length) {
76 resolve(prev)
77 }
78 }, r=> {
79 reject(r)
80 })
81 } else {
82 prev[i] = curr;
83 }
84 return prev;
85 }, [])
86 })
87 }
88 static resolve (v) {
89 if (v instanceof Promise) return v;
90 return new Promise((resolve ,reject) => resolve(v));
91 }
92 static reject(r) {
93 return new Promise((resolve,reject)=>{
94 reject(r)
95 })
96 }
97 static allSettled (args) {
98 return new Promise((resolve, reject) => {
99 function addData(prev, index, value){
100 prev[index] = value;
101 if (prev.length === args.length) {
102 resolve(prev)
103 }
104 }
105 args.reduce((prev, curr, index, arr) => {
106 if (curr instanceof Promise) {
107 curr.then(res => {
108 addData(prev, index, {
109 value: res,
110 status: 'fulfilled'
111 })
112 }, r => {
113 addData(prev, index, {
114 reason: r,
115 status: 'rejected'
116 })
117 })
118 } else {
119 addData(prev, index, {
120 reason: curr,
121 status: 'fulfilled'
122 })
123 }
124 })
125 })
126 }
127
128 static race(args) {
129 return new Promise((resolve, reject) => {
130 args.forEach((item) => {
131 if (item instanceof Promise) {
132 item.then(v => {
133 resolve(v)
134 }, r => {
135 reject(r)
136 })
137 } else {
138 resolve(item)
139 }
140 })
141 })
142 }
143
144 finally (cb) {
145 return this.then(v => {
146 return Promise.resolve(cb()).then(() => v);
147 }, r => {
148 return Promise.resolve(cb()).then(() => { throw r })
149 })
150 }
151
152 resolve = (v) => {
153
154 //只有状态为pending才执行
155 if (this.status === PENDING) {
156 this.status = RESOLVED;
157 this.value = v;
158 this.onFullFilledCallbacks.forEach(c => c())
159 }
160 }
161
162 reject = (r) => {
163 if (this.status === PENDING) {
164 this.status = REJECTED;
165 this.reason = r;
166 this.onRejectedCallbacks.forEach(c => c())
167 }
168 }
169
170 then(onFullFilled, onRejected) {
171 //onFullFilled onRejected类型判断
172 if (typeof onFullFilled !== 'function') onFullFilled = v => v;
173 if (typeof onFullFilled !== 'function') {
174 onRejected = r => {
175 throw r;
176 }
177 }
178 const promise2 = new Promise((resolve, reject) => {
179 if (this.status === RESOLVED) {
180 // Promise为微任务,所以放到微任务队列执行
181 queueMicrotask(() => {
182 try {
183 const x = onFullFilled(this.value);
184 resolvePromise(x, promise2, resolve, reject)
185 } catch (e) {
186 reject(e)
187 }
188 })
189 }
190
191 if (this.status === REJECTED) {
192 queueMicrotask(() => {
193 try {
194 const x = onRejected(this.reason)
195 resolvePromise(x, promise2, resolve, reject)
196 } catch (e) {
197 reject(e)
198 }
199 })
200 }
201
202 if (this.status === PENDING) {
203 //如果状态为pending,则执行方法放入数组中,等待resolve或reject时候执行
204 this.onFullFilledCallbacks.push(() => {
205 queueMicrotask(() => {
206 try {
207 const x = onFullFilled(this.value);
208 resolvePromise(x, promise2, resolve, reject)
209 } catch (e) {
210 reject(e)
211 }
212 })
213 })
214
215 this.onRejectedCallbacks.push(() => {
216 queueMicrotask(() => {
217 try {
218 const x = onRejected(this.reason);
219 resolvePromise(x, promise2, resolve, reject)
220 } catch (e) {
221 reject(e)
222 }
223 })
224 })
225 }
226 })
227 return promise2;
228 }
229 }
230
231 Promise.deferred = function() {
232 var result = {};
233 result.promise = new Promise(function(resolve, reject){
234 result.resolve = resolve;
235 result.reject = reject;
236 });
237
238 return result;
239 }
240
241 module.exports = Promise;