【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--参数自动映射篇(6/8)...
文章目錄
前情概要
路由、action的掃描、發(fā)現(xiàn)、注冊搞定之后,后來我發(fā)現(xiàn)在我們的action里面獲取參數(shù)往往都是通過request對象來一個(gè)一個(gè)獲取。同樣的一行代碼我們不厭其煩的重復(fù)寫了無數(shù)次。遂想著那我們能不能像后端程序一樣做得更自動(dòng)化一些呢?
所以,接下來我們再來完成一個(gè)比較重要的功能,那就是參數(shù)的自動(dòng)綁定。
參數(shù)的自動(dòng)綁定實(shí)現(xiàn)思路
依靠ts的裝飾器特性,我們能做在方法上,在類上,在方法的參數(shù)上,在類的屬性成員上通通可以加上裝飾器來存放一些額外的數(shù)據(jù)。那理論上我們在編碼階段就可以通過一定的手段把這個(gè)標(biāo)記加載我們需要處理的方法、類、參數(shù)等上面,等到運(yùn)行時(shí)的時(shí)候可以根據(jù)這些額外的參數(shù)來幫我們做一些重復(fù)性的工作。
參數(shù)的自動(dòng)綁定實(shí)現(xiàn)---裝飾器實(shí)現(xiàn)
部分代碼,只貼了fromquery,其他幾個(gè)formbody,fromheader之類的基本一樣,都是調(diào)用makeActionParameterDescriptor方法
/*** 指示當(dāng)前參數(shù)從request對象的query中解析* * @export* @param {(target?: any) => Function} type * @returns {Function} */ export function fromQuery(type: (target?: any) => Function): Function; /*** 指示當(dāng)前參數(shù)從request對象的query中解析* * @export* @returns {Function} */ export function fromQuery(): Function {var thatArg = arguments;return function (target: Object, propertyKey: string, parameterIndex: number) {makeActionParameterDescriptor('query', thatArg, target, propertyKey, parameterIndex);} } function makeActionParameterDescriptor(parameterFromType: parameterFromType, thatArg: IArguments, target: Object, propertyKey: string, parameterIndex: number) {//非聲明在屬性和參數(shù)上if (!propertyKey) return;var paramType = undefined;var val = new ActionParamDescriptor();val.parameterName = propertyKey;val.target = target;val.parameterIndex = parameterIndex;val.parameterFromType = parameterFromType;val.parameterTypeType = 'simple'if (typeof parameterIndex === 'undefined') {//聲明在類的屬性上val.localtionType = 'classProperty'} else {//聲明在action的參數(shù)上val.localtionType = 'methodParameter'val.actionMethodName = propertyKey;val.parameterName = getArgs((target as any)[propertyKey])[parameterIndex];}//復(fù)雜類型if (thatArg.length > 0) {val.parameterTypeType = 'complex'val.parameterType = thatArg[0](target);}SetActionParamDescriptor(val); } function getArgs(func: Object) {//匹配函數(shù)括號(hào)里的參數(shù) var method = func.toString();method = method.length > 500 ? method.substring(0, 500) : method;method = method.replace("\r|\n|\\s", "")var args = method.match(/.*?\(.*?\)/i);if (args == null) throw Error('can not match method parameters');method = args[0];method = method.replace(/.*?\(|\)/, "").replace(')', '');//分解參數(shù)成數(shù)組 var arr = method.split(",").map(function (arg) {//去空格和內(nèi)聯(lián)注釋 return arg.replace(/\/\*.*\*\//, "").trim();}).filter(function (args) {//確保沒有undefineds return args;});return arr }ActionParamDescriptor 對象結(jié)構(gòu)
export declare type parameterFromType = 'query' | 'body' | 'form' | 'header' | 'cookie' | 'auto' export class ActionParamDescriptor {/*** action參數(shù)的action名稱* * @type {string}* @memberof ActionParamDescriptor*/actionMethodName: string/*** 參數(shù)名稱* * @type {string}* @memberof ActionParamDescriptor*/parameterName: string/*** 參數(shù)所在類* * @type {Object}* @memberof ActionParamDescriptor*/target: Object/*** 參數(shù)類型的類別* * @type {('complex' | 'simple')}* @memberof ActionParamDescriptor*/parameterTypeType: 'complex' | 'simple'/*** 參數(shù)對象的類型(class)對象* * @type {Function}* @memberof ActionParamDescriptor*/parameterType: Function/*** 參數(shù)所在參數(shù)類別的順序* * @type {(number | undefined)}* @memberof ActionParamDescriptor*/parameterIndex: number | undefined/*** 當(dāng)前參數(shù)屬性屬于什么類型* * @type {('classProperty'|'methodParameter')}* @memberof ActionParamDescriptor*/localtionType: 'classProperty' | 'methodParameter'/*** 標(biāo)記參數(shù)應(yīng)該從什么地方解析* * @type {parameterFromType}* @memberof ActionParamDescriptor*/parameterFromType: parameterFromType }參數(shù)的自動(dòng)綁定實(shí)現(xiàn)---基本使用方法
可以在action上標(biāo)記某一個(gè)參數(shù)從什么地方(query、form、body、cookie、header)進(jìn)行解析,
也可以標(biāo)記某個(gè)參數(shù)是一個(gè)復(fù)雜的查詢參數(shù),可以指定這個(gè)參數(shù)的類型。
當(dāng)然復(fù)雜的查詢class的每一個(gè)屬性都可以指定解析來源,當(dāng)然也必須使用裝飾器來修飾一下,不然我們就沒法知道有這個(gè)屬性需要進(jìn)行解析啦。
參數(shù)的自動(dòng)綁定實(shí)現(xiàn)---參數(shù)的說明元數(shù)據(jù)保存
reflect-metadata 目前來說也還是ts的一個(gè)實(shí)驗(yàn)性特性。可以用來輔助我們保存一些額外的數(shù)據(jù)。或者也可以理解成它是一個(gè)系統(tǒng)級別的靜態(tài)字典。
那我們把對參數(shù)的一些特別設(shè)置都通過reflect-metadata保存下來,其實(shí)這里我們自己使用一個(gè)對象來保存也是可以的。
參數(shù)的自動(dòng)綁定實(shí)現(xiàn)---參數(shù)的自動(dòng)解析和對象生成
嗯,大概是一些雜亂無章的代碼(^_^)。
主要思路:
需要說明的是,在這里有一個(gè)問題沒有解決。當(dāng)參數(shù)指定類型為body的時(shí)候,我們沒有對參數(shù)進(jìn)行更多的解析。也就意味著我申明的對象只有2個(gè)屬性,提交的body有3個(gè)屬性,最終在action里面的這個(gè)參數(shù)能拿到3個(gè)屬性。一直猶豫是否要做這里是否要做filter。
從后端的角度來說是毫無疑問的,不可能我一個(gè)class只聲明了2個(gè)屬性,而到運(yùn)行時(shí)的時(shí)候能取出來3個(gè)屬性。這是不可能的。
但從前端的角度來講,這也許是一個(gè)比較好的特性。某些時(shí)候更省事情。比較接口部分參數(shù)透傳的時(shí)候之類的。
參數(shù)的自動(dòng)解析大致就到這里了,嗯,這部分代碼可能有點(diǎn)小邏輯。又加上沒有注釋有點(diǎn)難理解。不過我覺得這樣挺好的,哈哈哈
轉(zhuǎn)載于:https://www.cnblogs.com/calvinK/p/nodejs-mvc-params-auto-mapping.html
總結(jié)
以上是生活随笔為你收集整理的【nodejs】让nodejs像后端mvc框架(asp.net mvc)一样处理请求--参数自动映射篇(6/8)...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图解java工程师学习路线
- 下一篇: 如何在FineUIMvc(ASP.NET