手写promise第三天
2020-09-24
手写promise第三天
静态方法all:
- all作为promise中的一个静态方法 只能通过Promise.all调用
- all接收一个数组作为参数 这个数组中的值可以是普通值 也可以是promise对象
- all方法会等数组中所有promise执行完之后统一返回一个数组
静态方法resolve:
- resolve接收一个值作为参数 这个值可以是普通值也可以是promise对象
- 如果是promise对象 那么直接返回
- 如果是普通值 那么将普通值包裹在promise里再返回
catch方法:
- 在promise的then方法中 一旦出现错误 由于then的特性 这个错误会一直传递到最后
- catch方法就是写在最后捕获这个错误的
finally:
- 无论promise最后是成功还是失败 值都会传到finally方法中去
- finally接收一个回调函数作为参数 并返回一个新的promise 在新promise的then中
- 可以拿到promise最后成功或失败的值
- 如果callback的返回值是一个异步的promise
- 那么then应该等异步的promise执行完才能执行
const PENDING = 'pengding'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; class MyPromise { status = PENDING; // 当前promise的状态 value = undefined; // 当前promise的值 reason = undefined; // 当前promise如果失败 失败的原因 successCallbacks = []; // 如果异步 那么将回调存入到对应回调库中 rejectCallbacks = []; // promise 的构造函数接受一个执行器 这个执行器会立即执行 constructor(executor) { // 这个执行器接收两个参数 第一个参数是执行成功 第二个是失败 // 在执行器执行的过程中如果resolve执行 那么这个promise成功 try { executor(this.resolve, this.reject); } catch (error) { this.reject(error); } } // all方法接收一个数组作为参数 // 例如['a', p1, p2, p3, 'b'] 其中p1p2p3是promise对象 static all(array) { let count = 0; let results = []; // 声明一个结果数组 接收数组每一项的结果 return new MyPromise((res, rej) => { // all方法返回一个新的promise对象 function setData(index, value) { // 往results里面放值的函数 count++; // 没放入一个值 处理过的数量加1 results[index] = value; // results对应项设置好值 if (count === array.length) { // 如果处理过值的总数已经等于array的长度 说明所有的值都处理完了 res(results); // 返回成功的结果 } } for (let i = 0; i < array.length; i++) { if (array[i] instanceof MyPromise) { // 如果这一项是promise类型的 array[i].then((val) => { // 那么等promise执行完 在then里面拿到执行结果再往results数组里放 setData(i, val); }, reason => { rej(reason); // 如果有一项的promise出错了 直接rej }); } else { // 如果是普通值 直接往数组里放 setData(i, array[i]); } } }) } // 静态resolve接收一个参数 static resolve(value) { if (value instanceof MyPromise) return value; // 如果这个参数是promise对象 那么直接返回 return new MyPromise(resolve => resolve(value)); // 如果不是 用promise包裹后返回 } // 成功调用resolve方法 接收一个参数作为这个promise的返回值存在promise对象中 resolve = data => { // 一旦status状态不是pending 那么就不再执行 保证状态不可逆 if (this.status !== PENDING) return; this.status = FULFILLED; this.value = data; // 将promise成功获得的数据存在value中 // 判断成功回调函数库中是否用未执行的函数 有的话依次执行 while (this.successCallbacks.length) { this.successCallbacks.shift()(); } } // 同resolve reject = reason => { if (this.status !== PENDING) return; this.status = REJECTED; this.reason = reason; while (this.rejectCallbacks.length) this.rejectCallbacks.shift()(); } // then方法 接收两个函数作为参数 第一个是成功的回调 then = (successCallback, rejectCallback) => { successCallback = successCallback || (value => value); rejectCallback = rejectCallback || (reason => { throw reason }); // then方法 返回的是一个新的promise对象 所以在执行then的时候 new一个新的promise // 同样的 这个新promise的执行器也会立即执行 let promise2 = new MyPromise((resolve, reject) => { // 当执行到then方法时候 status已经是FULFILLED说明promise已经执行成功 // 直接执行成功的回调 // 同时将成功回调的返回值传递给下一个promise的resolve方法 setTimeout(() => { try { if (this.status === FULFILLED) { const thenReturnVal = successCallback(this.value); resolvePromise(promise2, thenReturnVal, resolve, reject); } else if (this.status === REJECTED) { const thenReturnVal = rejectCallback(this.reason); resolvePromise(promise2, thenReturnVal, resolve, reject); } else { this.successCallbacks.push(() => { try { const thenReturnVal = successCallback(this.value); resolvePromise(promise2, thenReturnVal, resolve, reject); } catch (error) { reject(error); } }); this.rejectCallbacks.push(() => { try { const thenReturnVal = rejectCallback(this.reason); resolvePromise(promise2, thenReturnVal, resolve, reject); } catch (error) { reject(error); } }) } } catch (error) { reject(error); } }, 0); }); return promise2; } finally = callback => { // finally 也返回一个新的promise 在这个新promise的then方法里可以拿到最后成功或失败的值 return this.then(value => { // 利用then方法可以直到最后是成功了还是失败了 无论成功还是失败都要执行callback // 如果callback的返回值是一个异步的promise 利用resolve静态方法包裹这个返回值 // 例如 如果callback回调返回了 p3 而p3是一个延迟2秒执行的promise // 那么MyPromise.resolve(p3) === p3 也就是 p3.then。。。这样finally就会等这个promise执行完 才会调用then方法 return MyPromise.resolve(callback()).then(() => value); }, reason => { // 同样的 如果callback的promise是失败的 那么执行抛出这个reason return MyPromise.resolve(callback()).then(() => { throw reason }); }); // 调用then方法获取当前promise的状态 } // promise中一旦某一处有错误发生 会因为then的特性一直传递下去 直到最后这个catch里 catch = rejectCallback => { return this.then(undefined, rejectCallback); } } function resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { reject(new TypeError('重复调用自己了哦~')); } if (x instanceof MyPromise) { // 是promise对象 那需要调用Promise的then方法判断这个promise是否成功 // 如果成功 调用resolve方法 并且把值传递下去 如果失败 调用reject并且把原因传递下去 x.then(value => resolve(value), reason => reject(reason)); // x.then(resolve, reject); } else { resolve(x); } } const p1 = new MyPromise((resolve, reject) => { resolve('p1 complete'); }) const p2 = new MyPromise((resolve, reject) => { setTimeout(() => { resolve('p2 complete'); }, 1000); }) const p3 = new MyPromise((resolve, reject) => { setTimeout(() => { resolve('p3 complete'); }, 2000); }) // let all = MyPromise.all(['a', p1, p2, p3, 'b']); // all.then(value => { // console.log(value); // }, reason => { // console.log(reason); // }) // MyPromise.resolve(100).then(value => console.log(value)); // MyPromise.resolve(p2).then(value => console.log(value)); // p1.finally(() => { // console.log('finally'); // return p3; // }).then(val => console.log(val), reason => console.warn(reason)); p1 .then(() => { console.log(66666) throw new Error('error'); }) .then(value => console.log(value)) .catch(reason => { console.log(reason); });
总结:
- 还还还还没还还有还还处理then中的异步问题
- finally和then还是有些混乱...
- 在调用到reject的情况有两种 一是then中成功回调报错 二是直接调用reject方法