当前位置: 首页 > 后端技术 > Node.js

如何更好地理解中间件和洋葱模型

时间:2023-04-04 01:36:22 Node.js

鐩镐俊鐢ㄨ繃Koa銆丷edux鎴栬€匛xpress鐨勫皬浼欎即閮藉涓棿浠朵笉闄岀敓锛屽挨鍏舵槸鍦ㄥ涔燢oa鐨勮繃绋嬩腑锛屼篃浼氭帴瑙﹀埌鈥滄磱钁辨ā鍨嬧€濄€傛湰绡囧寘鍝ュ皢鍜屽ぇ瀹朵竴璧峰涔燢oa鐨勪腑闂翠欢锛屼笉杩囪繖閲屽寘鍝ヤ竴寮€濮嬪苟涓嶆墦绠楀睍绀哄ぇ瀹剁啛鐭ョ殑鈥滄磱钁辨ā鍨嬪浘鈥濓紝鑰屾槸鍏堜粙缁嶄竴涓婯oa涓粈涔堟槸涓棿浠讹紵鎯充簡瑙f洿澶氬彲浠ヨ闂煈夐樋瀹濆摜Github涓汉涓婚〉1.Koa涓棿浠跺湪@types/koa-compose鍖呬笅鐨刬ndex.d.ts澶存枃浠朵腑锛屾垜浠壘鍒颁簡涓棿浠剁被鍨嬬殑瀹氫箟锛?/@types/koa-compose/index.d.tsdeclarenamespacecompose{typeMiddleware=(context:T,next:Koa.Next)=>any;typeComposedMiddleware=(context:T,next?:Koa.Next)=>Promise;}//@types/koa/index.d.ts=>Koa.NexttypeNext=()=>Promise<浠讳綍>;閫氳繃瑙傚療Middleware绫诲瀷鐨勫畾涔夛紝鎴戜滑鍙互鐭ラ亾锛屽湪Koa涓紝middleware鏄竴涓櫘閫氱殑鍑芥暟锛屽畠鎺ユ敹涓や釜鍙傛暟锛歝ontext鍜宯ext銆傚叾涓璫ontext浠h〃涓婁笅鏂囧璞★紝next浠h〃涓€涓嚱鏁板璞★紝璋冪敤鍚庤繑鍥炰竴涓狿romise瀵硅薄銆備簡瑙d簡Koa鐨勪腑闂翠欢鏄粈涔堜箣鍚庯紝鎴戜滑鏉ヤ粙缁嶄竴涓婯oa涓棿浠剁殑鏍稿績锛屽嵆compose鍑芥暟锛歠unctionwait(ms){returnnewPromise((resolve)=>setTimeout(resolve,ms||1));}constarr=[];conststack=[];//绫诲瀷Middleware=(context:T,next:Koa.Next)=>any;stack.push(async(context,next)=>{arr.push(1);awaitwait(1);awaitnext();awaitwait(1);arr.push(6);});stack.push(async(context,next)=>{arr.push(2);awaitwait(1);awaitnext();awaitwait(1);arr.push(5);});鍫嗐€傛帹閫侊紙寮傛锛堜笂涓嬫枃锛屼笅涓€涓級=>{arr.push锛?锛夛紱绛夊緟绛夊緟锛?锛夛紱绛夊緟涓嬩竴涓紙锛夛紱绛夊緟绛夊緟锛?锛夛紱arr.push锛?锛夛紱}锛夛紱绛夊緟鎾板啓锛堝爢鏍堬級锛坽}锛夛紱涓婇潰浠g爜鐨勬潵婧愶細https://github.com/koajs/comp...瀵逛簬涓婇潰鐨勪唬鐮侊紝鎴戜滑甯屾湜鍦╟ompose(stack)({})璇彞鎵ц鍚庯紝鏁扮粍arr鐨勫€间负[1銆?銆?銆?銆?銆?]銆傝繖閲屾垜浠笉鍏冲績compose鍑芥暟鏄浣曞疄鐜扮殑銆傛垜浠潵鍒嗘瀽涓€涓嬨€傚鏋滆姹傛暟缁刟rr杈撳嚭鎯宠鐨勭粨鏋滐紝浠ヤ笂涓変釜涓棿浠剁殑鎵ц杩囩▼锛?.寮€濮嬫墽琛岀涓€涓腑闂翠欢锛屽皢1鍘嬪叆arr鏁扮粍锛宎rr鏁扮粍鐨勫€间负[1]锛屼互鍙婄劧鍚庣瓑寰?姣銆備负浜嗕繚璇乤rr鏁扮粍鐨勭涓€椤规槸2锛屾垜浠渶瑕佸湪璋冪敤next鍑芥暟鍚庡紑濮嬫墽琛岀浜屼釜涓棿浠躲€?銆佸紑濮嬫墽琛岀浜屼釜涓棿浠讹紝灏?鍘嬪叆arr鏁扮粍銆傛鏃禷rr鏁扮粍鐨勫€间负[1,2]锛岀户缁瓑寰?姣銆備负浜嗕繚璇乤rr鏁扮粍鐨勭浜岄」涓?锛屾垜浠繕闇€瑕佸湪璋冪敤next鍑芥暟鍚庡紑濮嬫墽琛岀涓変釜涓棿浠躲€?銆佸紑濮嬫墽琛岀涓変釜涓棿浠讹紝灏?鍘嬪叆arr鏁扮粍銆傛鏃禷rr鏁扮粍鐨勫€间负[1,2,3]锛岀户缁瓑寰?姣銆備负浜嗕繚璇乤rr鏁扮粍鐨勭涓夐」鏄?锛屾垜浠姹傚湪璋冪敤绗笁涓腑闂磏ext鍑芥暟鍚庯紝蹇呴』缁х画鎵ц銆?銆佺涓変釜涓棿浠舵墽琛屽畬鎴愬悗锛宎rr鏁扮粍鐨勫€间负[1,2,3,4]銆傚洜姝わ紝涓轰簡淇濊瘉arr鏁扮粍鐨勭4椤逛负5锛屾垜浠渶瑕佸湪绗笁涓腑闂翠欢鎵ц瀹屾瘯鍚庤繑鍥炲埌绗簩涓腑闂翠欢鐨刵ext鍑芥暟鍚庢墽琛岃鍙ャ€?銆佺浜屼釜涓棿浠舵墽琛屽畬鎴愬悗锛宎rr鏁扮粍鐨勫€间负[1,2,3,4,5]銆傚悓鏍凤紝涓轰簡淇濊瘉arr鏁扮粍鐨勭5椤逛负6锛屾垜浠渶瑕佸湪绗簩涓腑闂翠欢鎵ц瀹屾瘯鍚庯紝鍐嶆墽琛岃繑鍥炲埌绗竴涓腑闂翠欢鐨刵ext鍑芥暟鍚庣殑璇彞銆?銆佺涓€涓腑闂翠欢鎵ц鏃讹紝arr鏁扮粍鐨勫€间负[1,2,3,4,5,6]銆備负浜嗘洿鐩磋鐨勭悊瑙d笂闈㈢殑鎵ц杩囩▼锛屾垜浠彲浠ユ妸姣忎釜涓棿浠剁湅鎴愪竴涓ぇ浠诲姟锛岀劧鍚庝互next鍑芥暟涓哄垎鐣岀偣锛屽皢姣忎釜澶т换鍔℃媶瑙f垚3涓猙eforeNext銆乶ext鍜宎fterNext灏忎换鍔°€備笂鍥句腑锛屾垜浠紑濮嬫墽琛屼腑闂翠欢1鐨刡eforeNext浠诲姟锛岀劧鍚庢寜鐓х传鑹茬澶寸殑鎵ц姝ラ瀹屾垚涓棿浠剁殑浠诲姟璋冨害銆?7.9K鐨刟xios椤圭洰鑳藉鍒颁粈涔堟湰鏂囬樋瀹濆摜浠庝换鍔℃敞鍐屻€佷换鍔$紪鎺掋€佷换鍔¤皟搴︿笁涓柟闈㈠垎鏋愪簡axios鎷︽埅鍣ㄧ殑瀹炵幇銆傚悓鏍凤紝闃垮疂鍝ュ皢浠庝互涓婁笁涓柟闈㈠垎鏋怟oa涓棿浠舵満鍒躲€?.1浠诲姟娉ㄥ唽鍦↘oa涓紝鎴戜滑鍒涘缓浜咾oa搴旂敤瀵硅薄鍚庯紝鍙互閫氳繃璋冪敤璇ュ璞$殑use鏂规硶鏉ユ敞鍐屼腑闂翠欢锛歝onstKoa=require('koa');constapp=newKoa();app.use(async(ctx,next)=>{conststart=Date.now();awaitnext();constms=Date.now()-start;console.log(`${ctx.method}${ctx.url}-${ms}ms`);});鍏跺疄use鏂规硶鐨勫疄鐜板緢绠€鍗曪紝鍦╨ib/application.js鏂囦欢涓紝鎴戜滑鎵惧埌浜嗗畠鐨勫畾涔夛細//lib/application.jsmodule.exports=classApplicationextendsEmitter{constructor(options){super();//鐪佺暐閮ㄥ垎浠g爜this.middleware=[];}use(fn){if(typeoffn!=='function')thrownewTypeError('middlewaremustbeafunction!');//鐪佺暐閮ㄥ垎浠g爜this.middleware.push(fn);褰掕繕杩欎釜锛泒}浠庝笂闈㈢殑浠g爜鍙互鐪嬪嚭锛寀se鏂规硶鍐呴儴浼氭鏌n鍙傛暟鐨勭被鍨嬶紝褰撴鏌ラ€氳繃鏃讹紝浼氬皢fn鎸囧悜鐨勪腑闂翠欢瀛樺叆涓棿浠舵暟缁勶紝鑰岃繖涓璞′篃琚繑鍥炰互鏀寔閾惧紡璋冪敤銆?.2浠?7.9KAxios椤圭洰涓殑浠诲姟瀹夋帓鍙互瀛﹀埌浠€涔堣繖绡囨枃绔犱腑闃垮疂鍝ュ弬鑰冧簡Axios鎷︽埅鍣ㄧ殑璁捐妯″瀷锛屾彁鐐煎嚭浜嗗涓嬮€氱敤鐨勪换鍔″鐞嗘ā鍨嬶細鍦ㄨ繖涓€氱敤妯″瀷涓紝闃垮疂鍝ヤ娇鐢≒utthepre-processor鍜屽悗澶勭悊鍣ㄥ垎鍒湪CoreWork鏍稿績浠诲姟鍓嶅悗瀹屾垚浠诲姟瀹夋帓銆傚浜嶬oa鐨勪腑闂翠欢鏈哄埗锛屽畠閫氳繃鍦╝waitnext()璇彞鍓嶅悗鍒嗗埆鏀剧疆棰勫鐞嗗櫒鍜屽悗澶勭悊鍣ㄦ潵瀹屾垚浠诲姟瀹夋帓銆?/璁$畻璇锋眰澶勭悊鏃堕棿鐨勪腑闂翠欢app.use(async(ctx,next)=>{conststart=Date.now();awaitnext();constms=Date.now()-start;console.log(`${ctx.method}${ctx.url}-${ms}ms`);});1.3浠诲姟璋冨害閫氳繃鍓嶉潰鐨勫垎鏋愶紝鎴戜滑宸茬粡鐭ラ亾閫氳繃app.use鏂规硶娉ㄥ唽鐨勪腑闂翠欢浼氳瀛樻斁鍦ㄥ唴閮ㄧ殑涓棿浠舵暟缁勪腑銆傝瀹屾垚浠诲姟璋冨害锛屾垜浠渶瑕佷笉鏂殑浠庝腑闂翠欢鏁扮粍涓彇鍑轰腑闂翠欢鎵ц銆備腑闂翠欢璋冨害绠楁硶灏佽鍦╧oa-compose鍖呬笅鐨刢ompose鍑芥暟涓€傝鍑芥暟鐨勫叿浣撳疄鐜板涓嬶細/***Compose`middleware`杩斿洖*涓€涓畬鍏ㄦ湁鏁堢殑涓棿浠讹紝鐢?鎵€鏈変紶閫掔殑涓棿浠剁粍鎴愩€?*@param{Array}middleware*@return{Function}*@apipublic*/functioncompose(middleware){//鐪佺暐閮ㄥ垎浠g爜returnfunction(context,next){//鏈€鍚庤皟鐢ㄧ殑涓棿浠?letindex=-1锛涜繑鍥炶皟搴︼紙0锛夛紱functiondispatch(i){if(i<=index)returnPromise.reject(newError("next()琚娆¤皟鐢?));绱㈠紩=鎴戯紱璁ゝn=涓棿浠禰i];if(i===middleware.length)fn=next;濡傛灉(!fn)杩斿洖Promise銆傝В鍐筹紙锛?灏濊瘯{杩斿洖鎵胯銆俽esolve(fn(context,dispatch.bind(null,i+1)));}catch(err){returnPromise.reject(err);}}};}compose鍑芥暟鎺ユ敹涓€涓暟缁勭被鍨嬬殑鍙傛暟锛岃皟鐢ㄥ嚱鏁板悗杩斿洖涓€涓柊鐨勫嚱鏁般€備笅闈㈡垜浠氨浠ュ墠闈㈢殑渚嬪瓙涓轰緥锛屽垎鏋愪竴涓媋waitcompose(stack)({});鐨勬墽琛岃繃绋嬨€傞檲杩般€?.3.1dispatch(0)浠庝笂鍥惧彲浠ョ湅鍑猴紝鍦ㄧ涓€涓腑闂翠欢鍐呴儴璋冪敤next鍑芥暟鏃讹紝鍏跺疄鏄湪缁х画璋冪敤dispatch鍑芥暟锛屾鏃跺弬鏁癷鐨勫€间负1銆?.3.2dispatch(1)浠庝笂鍥惧彲浠ョ湅鍑猴紝鍦ㄧ浜屼釜涓棿浠跺唴閮ㄨ皟鐢╪ext鍑芥暟鐨勬椂鍊欙紝渚濈劧浼氳皟鐢╠ispatch鍑芥暟锛屽弬鏁癷鐨勫€间负2銆?.3.3dispatch(2)浠庝笂鍥惧彲浠ョ湅鍑猴紝鍦ㄧ涓変釜涓棿浠跺唴閮ㄨ皟鐢╪ext鍑芥暟鏃讹紝浠嶇劧璋冪敤浜哾ispatch鍑芥暟銆傛鏃跺弬鏁癷鐨勫€间负3銆?.3.4dispatch(3)浠庝笂鍥惧彲浠ョ湅鍑猴紝褰撲腑闂翠欢鏁扮粍涓殑涓棿浠跺紑濮嬫墽琛屽悗锛屽鏋渘ext鍙傛暟鐨勫€间笉鏄皟搴︽椂鏄惧紡璁剧疆锛岃繑鍥炲埌涓嬩竴涓嚱鏁板悗鐨勮鍙ヤ細缁х画鎵ц銆傚綋绗笁涓腑闂翠欢鎵ц瀹屾垚鍚庯紝灏嗚繑鍥炴墽琛岀浜屼釜涓棿浠朵笅涓€涓嚱鏁颁箣鍚庣殑璇彞锛岀洿鍒版墽琛屽畬涓棿浠朵腑瀹氫箟鐨勬墍鏈夎鍙ャ€傚垎鏋愬畬compose鍑芥暟鐨勫疄鐜颁唬鐮侊紝鎴戜滑鏉ョ湅鐪婯oa鏄浣曚娇鐢╟ompose鍑芥暟鏉ュ鐞嗘敞鍐屼腑闂翠欢鐨勩€俢onstKoa=require('koa');constapp=newKoa();//Responseapp.use(ctx=>{ctx.body='澶у濂斤紝鎴戞槸闃垮疂鍝?;});app.listen(3000);浣跨敤涓婇潰鐨勪唬鐮侊紝鎴戝彲浠ュ揩閫熷惎鍔ㄤ竴涓湇鍔″櫒銆傚叾涓紝use鏂规硶鎴戜滑涔嬪墠宸茬粡鍒嗘瀽杩囦簡锛屾帴涓嬫潵鎴戜滑鏉ュ垎鏋恖isten鏂规硶銆傝鏂规硶鐨勫疄鐜板涓嬶細//lib/application.jsmodule.exports=classApplicationextendsEmitter{listen(...args){debug('listen');constserver=http.createServer(this.callback());杩斿洖server.listen(...args);}}鏄剧劧鍦╨isten鏂规硶鍐呴儴锛屼細鍏堣皟鐢∟ode.js鍐呯疆鐨凥TTP妯″潡鐨刢reateServer鏂规硶鍒涘缓鏈嶅姟鍣紝鐒跺悗寮€濮嬬洃鍚寚瀹氱鍙o紝鍗冲紑濮嬬瓑寰呭鎴风鐨勮繛鎺?鍙﹀锛屽湪璋冪敤http.createServer鏂规硶鍒涘缓HTTP鏈嶅姟鍣ㄦ椂锛屾垜浠紶鍏ョ殑鍙傛暟鏄痶his.callback()銆傝鏂规硶鐨勫叿浣撳疄鐜板涓嬶細//lib/application.jsconstcompose=require('koa-compose');module.exports=classApplicationextendsEmitter{callback(){constfn=compose(this.middleware);濡傛灉(!this.listenerCount('error'))this.on('error',this.onerror);consthandleRequest=(req,res)=>{constctx=this.createContext(req,res);杩斿洖this.handleRequest(ctx,fn);};杩斿洖鍙ユ焺璇锋眰锛泒}鍦ㄥ洖璋冩柟娉曢噷闈紝鎴戜滑缁堜簬鐪嬪埌浜嗕箙杩濈殑compose鏂规硶銆傝皟鐢ㄥ洖璋冩柟娉曞悗锛屽皢杩斿洖handleRequest鍑芥暟瀵硅薄鏉ュ鐞咹TTP璇锋眰銆傛瘡褰揔oa鏈嶅姟鍣ㄦ敹鍒板鎴风璇锋眰鏃讹紝閮戒細璋冪敤handleRequest鏂规硶锛岃鏂规硶浼氬厛鍒涘缓涓€涓柊鐨凜ontext瀵硅薄锛岀劧鍚庢墽琛屾敞鍐岀殑涓棿浠舵潵澶勭悊鏀跺埌鐨凥TTP璇锋眰锛歮odule.exports=classApplicationextendsEmitter{handleRequest(ctx,fnMiddleware){constres=ctx.res;res.statusCode=404;constonerror=err=>ctx.onerror(err);consthandleResponse=()=>respond(ctx);onFinished(res,onerror);杩斿洖fnMiddleware(ctx)銆傛帴涓嬫潵鎴戜滑浠嬬粛娲嬭懕妯″瀷鍙婂叾搴旂敤銆?.娲嬭懕妯″瀷2.1娲嬭懕妯″瀷绠€浠嬶紙鏉ユ簮锛歨ttps://eggjs.org/en/intro/eg...锛夊湪涓婂浘涓紝娲嬭懕涓殑姣忎竴灞傞兘浠h〃浜嗕竴涓嫭绔嬬殑涓棿浠讹紝鐢ㄤ簬瀹炵幇涓嶅悓鐨勫姛鑳斤紝姣斿濡傚紓甯稿鐞嗐€佺紦瀛樺鐞嗙瓑銆傛瘡涓姹傞兘浼氫粠宸﹁竟寮€濮嬮€愬眰缁忚繃涓棿浠讹紝杩涘叆鏈€鍐呭眰涓棿浠跺悗锛屽啀浠庢渶鍐呭眰涓棿浠堕€愬眰杩斿洖銆傚洜姝わ紝瀵逛簬姣忎竴灞備腑闂翠欢锛屽湪涓€涓姹傚拰鍝嶅簲鍛ㄦ湡涓紝鏈変袱涓椂闂寸偣鍔犲叆涓嶅悓鐨勫鐞嗛€昏緫銆?.2onion妯″瀷鐨勫簲鐢ㄩ櫎浜唎nion妯″瀷鍦↘oa涓殑搴旂敤锛岃妯″瀷鍦℅ithub涓婄殑涓€浜涗笉閿欑殑椤圭洰涓篃鏈夊箍娉涚殑搴旂敤锛屾瘮濡俴oa-router鍜岄樋閲屽反宸寸殑midway锛寀mi-request绛夐」鐩€傚湪浠嬬粛浜咾oa鐨勪腑闂翠欢鍜屾磱钁辨ā鍨嬩箣鍚庯紝闃垮疂鍝ユ牴鎹嚜宸辩殑鐞嗚В鎻愮偧鍑轰簡濡備笅閫氱敤鐨勪换鍔″鐞嗘ā鍨嬶細://x-response-timeasyncfunctionresponseTime(ctx,next){conststart=newDate();绛夊緟涓嬩竴涓紙锛夛紱constms=newDate()-寮€濮嬶紱ctx.set("X-Response-Time",ms+"ms");}瀵逛簬姣忎釜涓棿浠讹紝棰勫鐞嗗櫒鍜屽悗澶勭悊鍣ㄦ槸鍙€夌殑銆備緥濡傦紝涓嬮潰鐨勪腑闂翠欢鐢ㄤ簬璁剧疆缁熶竴鐨勫搷搴斿唴瀹癸細//responseasyncfunctionrespond(ctx,next){awaitnext();濡傛灉锛堚€?鈥濓紒=ctx.url锛夎繑鍥烇紱ctx.body="浣犲ソ涓栫晫";}铏界劧涓婇潰浠嬬粛鐨勪袱涓腑闂翠欢姣旇緝绠€鍗曪紝浣嗘槸浣犱篃鍙互鏍规嵁鑷繁鐨勯渶瑕佸疄鐜板鏉傜殑閫昏緫銆侹oa鐨勬牳蹇冮潪甯歌交宸э紝灏忚€屽唴鑴忋€傞€氳繃鎻愪緵浼橀泤鐨勪腑闂翠欢鏈哄埗锛屽紑鍙戣€呭彲浠ョ伒娲诲湴鎵╁睍Web鏈嶅姟鍣ㄧ殑鍔熻兘銆傝繖绉嶈璁℃€濊矾鍊煎緱瀛︿範鍜屽€熼壌銆傚ソ浜嗭紝杩欐灏卞厛浠嬬粛鍒拌繖閲屽惂銆傚悗闈㈡湁鏈轰細闃垮疂鍝ヤ細鍗曠嫭浠嬬粛Redux鎴栬€匛xpress鐨勪腑闂翠欢鏈哄埗銆?.鍙傝€冭祫婧怟oa瀹樻柟鏂囨。Egg瀹樻柟鏂囨。