您的位置:首页 > 汽车 > 时评 > 中央气象台台风网电脑版_设计公司首页_论文收录网站排名_网站开发工程师

中央气象台台风网电脑版_设计公司首页_论文收录网站排名_网站开发工程师

2024/11/14 15:05:17 来源:https://blog.csdn.net/weixin_40710412/article/details/142650640  浏览:    关键词:中央气象台台风网电脑版_设计公司首页_论文收录网站排名_网站开发工程师
中央气象台台风网电脑版_设计公司首页_论文收录网站排名_网站开发工程师

昨天写完了填坑,从零带你手写Promise (typescript)-CSDN博客 发现代码还有一些可以优化的地方,在这里补充一下!

当然了,如果你只想了解promise的基本实现,那么上一篇文章足够且足以应对面试官了!

下面说一下MyPromise和官方Promise相差的一点特性

我们知道,Promise.resolve / Promise.then的onFulfilled/OnRejected / executor的resolve函数,是可以接受thenable的类promise的,如下所示:

Promise.resolve({then(a,b){a(1000)}
})//Promise {<fulfilled>: 1000}

昨天我们实现的MyPromise也能实现这一点,因为在then/MyPromise.resolve中加入了鸭子检测,并且调用了thenable中的then方法,如下:

   /** duck检测 */
if (MyPromise._duckTest(thenOriginResult)) {thenOriginResult.then(resolve, reject);
} else {/** 都不是 按照普通类型处理 */resolve(thenOriginResult);
}MyPromise.resolve({then(a, b) {a(10000)}}).then(val=>{console.log(val)}) // 10000

 但是当thenable层数变多时,比如thenable的then方法再resolve/reject一个thenable时,官方的Promise可以一直调用到最底层,如下:

const thenable = {then(a,b){a({then(a,b){a(10000)}})}
}
Promise.resolve(thenable)
// Promise {<fulfilled>: 10000}

但是对于我们自己实现的MyPromise只能实现一层的then调用,如下:

        const thenable = {then(a, b) {a({then(a, b) {a(10000)}})}}console.log(MyPromise.resolve(thenable))

这个问题如何解决? 其实如果我们缩紧thenable的范围,使用MyPromise对象,即可达到想要的效果:

console.log(
MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(MyPromise.resolve(10000))))
)// val: 10000成功的promise

但是换成thenable类MyPromise就不行,原因就是因为,递归调用是在then方法内实现的,在MyPromise.prototype.then中,我们使用如下方法:

const thenOriginResult =state === EMyPromiseState.FULFILLED? onfulfilled(this.value): onRejected(this.value);if ((this as unknown as IMyPromise) === thenOriginResult) {throw new Error('then方法不能返回当前MyPromise对象!');}/** duck检测 */if (MyPromise._duckTest(thenOriginResult)) {thenOriginResult.then(resolve, reject);} else {/** 都不是 按照普通类型处理 */resolve(thenOriginResult);

当thenOriginResult(onFulfilled/onReject返回值)为thenable的时候,会调用其then决定新返回的promise的状态和值,如果thenOriginResult的结果再次为thenable时,会继续调用then方法,直到thenOriginResult为非thenable为止。

这样看上去没问题,但是我们需要注意,这里的then方法是在MyPromise对象上的,对于其他非MyPromise类型的thenable,是没有实现这个then方法的,其then方法可能没有循环调用的功能,所以只能实现单层的then调用,所以我们需要做的就是,在鸭子检测后判断

1. 如果thenable是MyPromise类型,直接调用then方法

2.如果不是,则实现一个函数,递归调用then后返回最终结果

我们将上面的过程,包含非thenable的情况封装成 _handleThenable函数如下:

    private static _handleThenable(thenableObj: any, resolve: OnFulfilled, reject: OnRejected) {if (thenableObj instanceof MyPromise) {return thenableObj.then(resolve, reject);} else if (typeof thenableObj.then === 'function') {return thenableObj.then((val: any) => {MyPromise._handleThenable(val, resolve, reject);},(reason: any) => {reject(reason);},);} else {return resolve(thenableObj);}}

这个函数会对传入的值判断

1. 如果是MyPromise类型,直接调用其then方法并且返回

2. 如果是 非MyPromise类型的thenable,则调用其then方法,在成功的回调中再次调用_handleThenable 递归处理

3. 如果不是thenable,resolve(val)

我们可以在then/MyPromise.resolve中调用该函数 做如下修改:

// then/** then方法 */public then(onfulfilled: OnFulfilled = (value) => value, // 设置默认onRejected: OnRejected = (reason) => {//设置默认,这里为了可以把错误传递下去throw reason;},) {return new MyPromise((resolve, reject) => {const thenTask = (state: EMyPromiseState = EMyPromiseState.FULFILLED) => {queueMicrotask(function () {try {/** 获得 onfulfilled / onRejected 返回的原始值  */const thenOriginResult =state === EMyPromiseState.FULFILLED? //@ts-ignoreonfulfilled(this.value): //@ts-ignoreonRejected(this.value);//@ts-ignoreif ((this as unknown as IMyPromise) === thenOriginResult) {throw new Error('then方法不能返回当前MyPromise对象!');}/** duck检测 */if (MyPromise._duckTest(thenOriginResult)) {MyPromise._handleThenable(thenOriginResult, resolve, reject);} else {/** 都不是 按照普通类型处理 */resolve(thenOriginResult);}} catch (err) {reject(err);}}.bind(this),);};if (this._isMyPrimiseDecided()) {/** 当promise已经决策, 直接运行onfulfilled/onRejected */thenTask(this.state);} else {/** 未决策,加入对应队列 两个都加入*/this.onFulfilledCallbacks.push(thenTask.bind(this, EMyPromiseState.FULFILLED));this.onRejectedCallbacks.push(thenTask.bind(this, EMyPromiseState.REJECTED));}});}// MyPromise.resolvepublic static resolve(value?: any) {/** duck检测 */if (MyPromise._duckTest(value)) {return new MyPromise((resolve, reject) => {MyPromise._handleThenable(value, resolve, reject);});}/** 都不是 按照普通类型处理 */return new MyPromise((resolve) => {resolve(value);});}

这样就完成了then方法和MyPromise.resolve方法对于thenable的递归调用,再次尝试结果如下:

 

同时,在executor中的resolve函数,也需要有递归调用thenable的功能,我们做如下修改,将_resolvePromise 和 _rejectPromise的具体实现提取出来,实现新的函数 _resolvePromiseImple和_rejectPromiseImple 如下:

    /** 用来决策成功promise实现 */private _resolvePromiseImpl = (value: any) => {this.value = value;this.state = EMyPromiseState.FULFILLED;this.onFulfilledCallbacks.forEach((onFulfilledCallback) => {onFulfilledCallback();});};/** 用来拒绝promise实现 */private _rejectPromiseImpl = (reason: any) => {/** 设置失败reason和状态 */this.value = reason;this.state = EMyPromiseState.REJECTED;/** 此时回调缓存可能有挂着的任务,执行*/this.onRejectedCallbacks.forEach((onRejectedCallback) => {onRejectedCallback();});};/** 用来决策成功promise */private _resolvePromise(inputVal?: any) {if (!this._isMyPrimiseDecided()) {/** promise状态只可以变化一次 *//** duck检测 */if (MyPromise._duckTest(inputVal)) {MyPromise.resolve(inputVal).then(this._resolvePromiseImpl, this._rejectPromiseImpl);} else {this._resolvePromiseImpl(inputVal);}}}/** 用来拒绝promise */private _rejectPromise(reason?: any) {if (!this._isMyPrimiseDecided()) {/** promise状态只可以变化一次 */this._rejectPromiseImpl(reason);}}

这样,我们在executor中的resolve中,也可以传入多层thenable如下:

        new MyPromise((resolve)=>{resolve(MyPromise.resolve(1000))}).then(val=>console.log(val)) // 输出1000new MyPromise(resolve=>resolve(new MyPromise(r=>{setTimeout(() => {r(1000)}, 2000);}))).then(val=>console.log(val)) // 2后输出1000

最终实现版本如下:

/** 实现一个Promise */
/** Promise状态枚举 */
enum EMyPromiseState {/** 未决策状态 */'PENDING' = 'pending',/** 成功状态 */'FULFILLED' = 'fulfilled',/** 拒绝状态 */'REJECTED' = 'rejected',}/** 成功回调类型 */type OnFulfilled = (value?: any) => any;/** 失败回调类型 */type OnRejected = (reason?: any) => any;/** 执行器 */type Executor = (resolve: OnFulfilled, reject: OnRejected) => void;/** MyPromise类型 */interface IMyPromise {/** 状态 */state: EMyPromiseState;/** 值 | 错误原因 */value: any;/** then方法,满足thenable协议 */then: (onfulfilled?: OnFulfilled, onRejected?: OnRejected) => IMyPromise;/** catch方法 */catch: (catchHandler: (err: any) => void) => void;/** finally 方法 */finally: (finallyHandler: () => void) => void;/** ---- 静态方法 ---- *//** 返回成功MyPromise */readonly resolve?: (value: any) => IMyPromise;/** 返回失败MyPromise */readonly reject?: (value: any) => IMyPromise;/** all方法 */readonly all?: (myPromises: IMyPromise[]) => IMyPromise;/** any方法 */readonly any?: (myPromises: IMyPromise[]) => IMyPromise;/** race方法 */readonly race?: (myPromises: IMyPromise[]) => IMyPromise;/** allSettled方法 */readonly allSettled?: (myPromises: IMyPromise[]) => IMyPromise[];}class MyPromise implements IMyPromise {/** 成功回调缓存 */private onFulfilledCallbacks: VoidFunction[] = [];/** 失败回调缓存 */private onRejectedCallbacks: VoidFunction[] = [];/** 状态 */public state: EMyPromiseState = EMyPromiseState.PENDING;/** value */public value: any;/** 用来判断promise是否已经决策 */private _isMyPrimiseDecided() {return this.state !== EMyPromiseState.PENDING;}/** 用来决策成功promise实现 */private _resolvePromiseImpl = (value: any) => {this.value = value;this.state = EMyPromiseState.FULFILLED;this.onFulfilledCallbacks.forEach((onFulfilledCallback) => {onFulfilledCallback();});};/** 用来拒绝promise实现 */private _rejectPromiseImpl = (reason: any) => {/** 设置失败reason和状态 */this.value = reason;this.state = EMyPromiseState.REJECTED;/** 此时回调缓存可能有挂着的任务,执行*/this.onRejectedCallbacks.forEach((onRejectedCallback) => {onRejectedCallback();});};/** 用来决策成功promise */private _resolvePromise(inputVal?: any) {if (!this._isMyPrimiseDecided()) {/** promise状态只可以变化一次 *//** duck检测 */if (MyPromise._duckTest(inputVal)) {MyPromise.resolve(inputVal).then(this._resolvePromiseImpl, this._rejectPromiseImpl);} else {this._resolvePromiseImpl(inputVal);}}}/** 用来拒绝promise */private _rejectPromise(reason?: any) {if (!this._isMyPrimiseDecided()) {/** promise状态只可以变化一次 */this._rejectPromiseImpl(reason);}}/** ctor 穿入执行器函数 */public constructor(executor: Executor) {try {/** 为了实现执行器内抛出异常自动拒绝 */executor(this._resolvePromise.bind(this), this._rejectPromise.bind(this));} catch (reason) {this._rejectPromise(reason);}}/** then方法 */public then(onfulfilled: OnFulfilled = (value) => value, // 设置默认onRejected: OnRejected = (reason) => {//设置默认,这里为了可以把错误传递下去throw reason;},) {return new MyPromise((resolve, reject) => {const thenTask = (state: EMyPromiseState = EMyPromiseState.FULFILLED) => {queueMicrotask(function () {try {/** 获得 onfulfilled / onRejected 返回的原始值  */const thenOriginResult =state === EMyPromiseState.FULFILLED? //@ts-ignoreonfulfilled(this.value): //@ts-ignoreonRejected(this.value);//@ts-ignoreif ((this as unknown as IMyPromise) === thenOriginResult) {throw new Error('then方法不能返回当前MyPromise对象!');}/** duck检测 */if (MyPromise._duckTest(thenOriginResult)) {MyPromise._handleThenable(thenOriginResult, resolve, reject);} else {/** 都不是 按照普通类型处理 */resolve(thenOriginResult);}} catch (err) {reject(err);}}.bind(this),);};if (this._isMyPrimiseDecided()) {/** 当promise已经决策, 直接运行onfulfilled/onRejected */thenTask(this.state);} else {/** 未决策,加入对应队列 两个都加入*/this.onFulfilledCallbacks.push(thenTask.bind(this, EMyPromiseState.FULFILLED));this.onRejectedCallbacks.push(thenTask.bind(this, EMyPromiseState.REJECTED));}});}/** 最后处理错误 */public catch(catchHandler: (err: any) => void = () => {}) {/** 相当于仅调用失败的promise */return this.then((val) => val,(err) => {catchHandler(err);},);}/** 最终处理 */public finally(finallyHandler: () => any = () => {}) {this.then(() => {finallyHandler();},() => {finallyHandler();},);}/** 鸭子检测:*  thenable协议: 对象/函数上包含then函数即可*/private static _duckTest(thenable: any) {return (thenable &&(typeof thenable === 'function' || typeof thenable === 'object') &&typeof thenable.then === 'function');}/** 递归处理thenable */private static _handleThenable(thenableObj: any, resolve: OnFulfilled, reject: OnRejected) {if (thenableObj instanceof MyPromise) {return thenableObj.then(resolve, reject);} else if (typeof thenableObj.then === 'function') {return thenableObj.then((val: any) => {MyPromise._handleThenable(val, resolve, reject);},(reason: any) => {reject(reason);},);} else {return resolve(thenableObj);}}/** 返回一个成功的MyPromise *//** 过滤thenable* 1. 如果是MyPrimise类型,判读是否是当前myPromise,防止形成环,是则报错,否则直接返回* 2. duck检测,检查是不是thenable,是则封装成MyPromise 否则直接封装到成功的MyPromise*/public static resolve(value?: any) {/** duck检测 */if (MyPromise._duckTest(value)) {return new MyPromise((resolve, reject) => {MyPromise._handleThenable(value, resolve, reject);});}/** 都不是 按照普通类型处理 */return new MyPromise((resolve) => {resolve(value);});}/** 返回一个失败的MyPromise */public static reject(reason?: any) {return new MyPromise((_, reject) => {reject(reason);});}public static all(myPromises: IMyPromise[]) {const resultList: any[] = [];let fulfilledCnt = 0;return new MyPromise((resolve, reject) => {for (let i = 0; i < myPromises.length; i++) {const myPrimise = myPromises[i];myPrimise.then((value) => {resultList[i] = value;if (++fulfilledCnt === myPromises.length) {resolve(resultList);}},() => {reject();},);}});}public static any(myPromises: IMyPromise[]) {const AggregateError: any[] = [];let rejectedCnt = 0;return new MyPromise((resolve, reject) => {for (let i = 0; i < myPromises.length; i++) {const myPrimise = myPromises[i];myPrimise.then((val) => {resolve(val);},(reason) => {AggregateError[i] = reason;if (++rejectedCnt === myPromises.length) {reject(AggregateError);}},);}});}public static race(myPromises: IMyPromise[]) {return new MyPromise((resolve, reject) => {myPromises.forEach((myPromise) => {myPromise.then(resolve, reject);});});}public static allSettled(myPromises: IMyPromise[]) {const resultList: any[] = [];let decideCnt = 0;return new MyPromise((resolve) => {for (let i = 0; i < myPromises.length; i++) {const myPrimise = myPromises[i];myPrimise.then((val) => {resultList[i] = {status: EMyPromiseState.FULFILLED,value: val,};if (++decideCnt === myPromises.length) {resolve(resultList);}},(reason) => {resultList[i] = {status: EMyPromiseState.REJECTED,value: reason,};if (++decideCnt === myPromises.length) {resolve(resultList);}},);}});}}/** 导出MyPromise */export default MyPromise;

你可以访问我的git获取项目源码: https://github.com/Gravity2333/my-promise-ts-imple

或者使用 npm i my-promise-ts-imple 下载使用学习

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com