From 124d3dd5474e63467d4de5217ffe9f74d2ada0c1 Mon Sep 17 00:00:00 2001 From: waiting <1661926154@qq.com> Date: Thu, 7 Nov 2024 11:53:23 +0800 Subject: [PATCH 1/3] refactor(core): MidwayMiddlewareService with dispatch() --- .../core/src/service/middlewareService.ts | 149 ++++++++++-------- 1 file changed, 87 insertions(+), 62 deletions(-) diff --git a/packages/core/src/service/middlewareService.ts b/packages/core/src/service/middlewareService.ts index 79a030fdfd35..3a30085c185d 100644 --- a/packages/core/src/service/middlewareService.ts +++ b/packages/core/src/service/middlewareService.ts @@ -91,68 +91,16 @@ export class MidwayMiddlewareService { const composeFn = (context: T, next?) => { const supportBody = isIncludeProperty(context, 'body'); // last called middleware # - let index = -1; - return dispatch(0); - - function dispatch(i) { - if (i <= index) - return Promise.reject( - new MidwayCommonError('next() called multiple times') - ); - index = i; - let fn = (newMiddlewareArr as Array>)[i]; - if (i === newMiddlewareArr.length) fn = next; - if (!fn) return Promise.resolve(); - const middlewareName = `${name ? `${name}.` : ''}${index} ${ - (fn as any)._name || fn.name || 'anonymous' - }`; - const startTime = Date.now(); - debug(`[middleware]: in ${middlewareName} +0`); - try { - if (supportBody) { - return Promise.resolve( - fn(context, dispatch.bind(null, i + 1), { - index, - } as any) - ).then(result => { - /** - * 1、return 和 ctx.body,return 的优先级更高 - * 2、如果 result 有值(非 undefined),则不管什么情况,都会覆盖当前 body,注意,这里有可能赋值 null,导致 status 为 204,会在中间件处进行修正 - * 3、如果 result 没值,且 ctx.body 已经赋值,则向 result 赋值 - */ - if (result !== undefined) { - context['body'] = result; - } else if (context['body'] !== undefined) { - result = context['body']; - } - debug( - `[middleware]: out ${middlewareName} +${ - Date.now() - startTime - } with body` - ); - return result; - }); - } else { - return Promise.resolve( - fn(context, dispatch.bind(null, i + 1), { - index, - } as any) - ).then(result => { - debug( - `[middleware]: out ${middlewareName} +${Date.now() - startTime}` - ); - return result; - }); - } - } catch (err) { - debug( - `[middleware]: out ${middlewareName} +${ - Date.now() - startTime - } with err ${err.message}` - ); - return Promise.reject(err); - } - } + const opts: DispatchOptions = { + context, + i: 0, + index: -1, + name, + newMiddlewareArr, + next, + supportBody, + }; + return dispatch(opts); }; if (name) { composeFn._name = name; @@ -160,3 +108,80 @@ export class MidwayMiddlewareService { return composeFn; } } + +interface DispatchOptions { + context: any; + i: number; + index: number; + name: string; + newMiddlewareArr: unknown[]; + next: FunctionMiddleware; + supportBody: boolean; +} + +function dispatch(options: DispatchOptions): Promise { + const { i, context, newMiddlewareArr, name, next, supportBody } = options; + + if (i <= options.index) { + return Promise.reject( + new MidwayCommonError('next() called multiple times') + ); + } + options.index = i; + let fn = (newMiddlewareArr as Array>)[i]; + if (i === newMiddlewareArr.length) { + fn = next; + } + if (!fn) return Promise.resolve(); + const middlewareName = `${name ? `${name}.` : ''}${options.index} ${ + (fn as any)._name || fn.name || 'anonymous' + }`; + const startTime = Date.now(); + debug(`[middleware]: in ${middlewareName} +0`); + try { + if (supportBody) { + const opts = { ...options, i: i + 1 }; + return Promise.resolve( + fn(context, dispatch.bind(null, opts), { + index: options.index, + } as any) + ).then(result => { + /** + * 1、return 和 ctx.body,return 的优先级更高 + * 2、如果 result 有值(非 undefined),则不管什么情况,都会覆盖当前 body,注意,这里有可能赋值 null,导致 status 为 204,会在中间件处进行修正 + * 3、如果 result 没值,且 ctx.body 已经赋值,则向 result 赋值 + */ + if (result !== undefined) { + context['body'] = result; + } else if (context['body'] !== undefined) { + result = context['body']; + } + debug( + `[middleware]: out ${middlewareName} +${ + Date.now() - startTime + } with body` + ); + return result; + }); + } else { + const opts = { ...options, i: i + 1 }; + return Promise.resolve( + fn(context, dispatch.bind(null, opts), { + index: options.index, + } as any) + ).then(result => { + debug( + `[middleware]: out ${middlewareName} +${Date.now() - startTime}` + ); + return result; + }); + } + } catch (err) { + debug( + `[middleware]: out ${middlewareName} +${ + Date.now() - startTime + } with err ${err.message}` + ); + return Promise.reject(err); + } +} From 30e3381bcb7890b79d1541f6509a6ad39b07db49 Mon Sep 17 00:00:00 2001 From: waiting <1661926154@qq.com> Date: Thu, 7 Nov 2024 16:32:17 +0800 Subject: [PATCH 2/3] chore(core): lint fix --- packages/core/src/service/middlewareService.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core/src/service/middlewareService.ts b/packages/core/src/service/middlewareService.ts index 3a30085c185d..da75a9b30b09 100644 --- a/packages/core/src/service/middlewareService.ts +++ b/packages/core/src/service/middlewareService.ts @@ -170,9 +170,7 @@ function dispatch(options: DispatchOptions): Promise { index: options.index, } as any) ).then(result => { - debug( - `[middleware]: out ${middlewareName} +${Date.now() - startTime}` - ); + debug(`[middleware]: out ${middlewareName} +${Date.now() - startTime}`); return result; }); } From ed8c4a95d7b0e0801ad2d9ac6445e1173b347bf1 Mon Sep 17 00:00:00 2001 From: waiting <1661926154@qq.com> Date: Sat, 9 Nov 2024 16:28:14 +0800 Subject: [PATCH 3/3] refactor(core): MidwayAspectService.interceptPrototypeMethod() with processAsync() and processSync() --- packages/core/src/service/aspectService.ts | 185 ++++++++++++--------- 1 file changed, 107 insertions(+), 78 deletions(-) diff --git a/packages/core/src/service/aspectService.ts b/packages/core/src/service/aspectService.ts index 67054419b3d1..fb6b107eba32 100644 --- a/packages/core/src/service/aspectService.ts +++ b/packages/core/src/service/aspectService.ts @@ -80,97 +80,126 @@ export class MidwayAspectService { * @param aspectObject aspect object, before, round, etc. */ public interceptPrototypeMethod( - Clz: new (...args) => any, + Clz: new (...args: any[]) => any, methodName: string, aspectObject: IMethodAspect | (() => IMethodAspect) ) { const originMethod = Clz.prototype[methodName]; if (Types.isAsyncFunction(Clz.prototype[methodName])) { - Clz.prototype[methodName] = async function (...args) { - let error, result; - const newProceed = (...args) => { - return originMethod.apply(this, args); - }; - const joinPoint = { + Clz.prototype[methodName] = async function (...args: unknown[]): Promise { + const opts: ProcessOptions = { + args, methodName, target: this, - args: args, - proceed: newProceed, - proceedIsAsyncFunction: true, - } as JoinPoint; - - if (typeof aspectObject === 'function') { - aspectObject = aspectObject(); - } - - try { - await aspectObject.before?.(joinPoint); - if (aspectObject.around) { - result = await aspectObject.around(joinPoint); - } else { - result = await originMethod.call(this, ...joinPoint.args); - } - joinPoint.proceed = undefined; - const resultTemp = await aspectObject.afterReturn?.( - joinPoint, - result - ); - result = typeof resultTemp === 'undefined' ? result : resultTemp; - return result; - } catch (err) { - joinPoint.proceed = undefined; - error = err; - if (aspectObject.afterThrow) { - await aspectObject.afterThrow(joinPoint, error); - } else { - throw err; - } - } finally { - await aspectObject.after?.(joinPoint, result, error); - } + }; + return processAsync(aspectObject, originMethod, opts); }; } else { - Clz.prototype[methodName] = function (...args) { - let error, result; - const newProceed = (...args) => { - return originMethod.apply(this, args); - }; - const joinPoint = { + Clz.prototype[methodName] = function (...args: unknown[]) { + const opts: ProcessOptions = { + args, methodName, target: this, - args: args, - proceed: newProceed, - proceedIsAsyncFunction: false, - } as JoinPoint; - - if (typeof aspectObject === 'function') { - aspectObject = aspectObject(); - } - - try { - aspectObject.before?.(joinPoint); - if (aspectObject.around) { - result = aspectObject.around(joinPoint); - } else { - result = originMethod.call(this, ...joinPoint.args); - } - joinPoint.proceed = undefined; - const resultTemp = aspectObject.afterReturn?.(joinPoint, result); - result = typeof resultTemp === 'undefined' ? result : resultTemp; - return result; - } catch (err) { - joinPoint.proceed = undefined; - error = err; - if (aspectObject.afterThrow) { - aspectObject.afterThrow(joinPoint, error); - } else { - throw err; - } - } finally { - aspectObject.after?.(joinPoint, result, error); - } + }; + return processSync(aspectObject, originMethod, opts); }; } } } + +interface ProcessOptions { + args: unknown[], + methodName: string; + target: any +} +async function processAsync( + aspectObjectInput: IMethodAspect | (() => IMethodAspect), + originMethod: Function, + options: ProcessOptions +): Promise { + + let error: Error; + let result: unknown; + const newProceed = (...args: unknown[]) => { + return originMethod.apply(this, args); + }; + const joinPoint = Object.assign({}, options, {proceed: newProceed, proceedIsAsyncFunction: true}) as JoinPoint; + + let aspectObject: IMethodAspect; + if (typeof aspectObjectInput === 'function') { + aspectObject = aspectObjectInput(); + } else { + aspectObject = aspectObjectInput; + } + + try { + await aspectObject.before?.(joinPoint); + if (aspectObject.around) { + result = await aspectObject.around(joinPoint); + } else { + result = await originMethod.call(this, ...joinPoint.args); + } + joinPoint.proceed = undefined; + const resultTemp = await aspectObject.afterReturn?.( + joinPoint, + result + ); + result = typeof resultTemp === 'undefined' ? result : resultTemp; + return result; + } catch (err) { + joinPoint.proceed = undefined; + error = err; + if (aspectObject.afterThrow) { + await aspectObject.afterThrow(joinPoint, error); + } else { + throw err; + } + } finally { + await aspectObject.after?.(joinPoint, result, error); + } +} + +function processSync( + aspectObjectInput: IMethodAspect | (() => IMethodAspect), + originMethod: Function, + options: ProcessOptions +): unknown { + + let error: Error; + let result: unknown; + const newProceed = (...args: unknown[]) => { + return originMethod.apply(this, args); + }; + const joinPoint = Object.assign({}, options, {proceed: newProceed, proceedIsAsyncFunction: false}) as JoinPoint; + + let aspectObject: IMethodAspect; + if (typeof aspectObjectInput === 'function') { + aspectObject = aspectObjectInput(); + } else { + aspectObject = aspectObjectInput; + } + + try { + aspectObject.before?.(joinPoint); + if (aspectObject.around) { + result = aspectObject.around(joinPoint); + } else { + result = originMethod.call(this, ...joinPoint.args); + } + joinPoint.proceed = undefined; + const resultTemp = aspectObject.afterReturn?.(joinPoint, result); + result = typeof resultTemp === 'undefined' ? result : resultTemp; + return result; + } catch (err) { + joinPoint.proceed = undefined; + error = err; + if (aspectObject.afterThrow) { + aspectObject.afterThrow(joinPoint, error); + } else { + throw err; + } + } finally { + aspectObject.after?.(joinPoint, result, error); + } +}