koa2 数据api中间件设计模型的实现方法
假设所有的数据库读取,httpapi接口请求都为一个中间件,将中间件当做插件,插入需要获取数据的位置。
api.js
module.exports=async(ctx,next)=>{ ctx.share_data.api_data=awaitaxios.get('/api'); awaitnext(); };
db.js
module.exports=async(ctx,next)=>{ ctx.share_data.db_data=awaitmysql_query('SELECTXXX').catch(()=>{}); awaitnext(); };
串联
app.js
constapi=require('api.js'); constdb=require('db.js'); app.get('/get-api',api,(ctx)=>ctx.body=ctx.share_data); app.get('/get-db',db,(ctx)=>ctx.body=ctx.share_data); app.get('/get-api-and-db',api,db,(ctx)=>ctx.body=ctx.share_data);
看着挺和谐,但是如果有多个数据中间件串联则会导致接口的响应时间为所有中间件的总和。
并发
可义一个compose函数,需要并发的中间件包装起来
super-compose.js
module.exports=(middleware=[])=>{ if(!Array.isArray(middleware))thrownewTypeError('Middlewarestackmustbeanarray!'); for(constfnofmiddleware){ if(typeoffn!=='function')thrownewTypeError('Middlewaremustbecomposedoffunctions!'); } returnasync(context={},next=f=>f)=>{ awaitPromise.all( middleware.map(middleware=>{ returnnewPromise((rs,rj)=>{ middleware(context,()=>Promise.resolve()) .then(rs) .catch(rj); }); }), ); awaitnext(); }; };
app.js
constapi=require('api.js'); constdb=require('db.js'); constsuperCompose=require('super-compose.js'); app.get('/get-api-and-db',superCompose([api,db]),(ctx)=>ctx.body=ctx.share_data);
依赖关系
看着貌似解决了,但如何处理具有上下文依赖的情况呢?例如api_1依赖api的数据。
改下api.js,加上缓存校验。处理可能被多次compose的重复接口调用
module.exports=async(ctx,next)=>{ if(ctx.share_data.api_data){ returnawaitnext(); } ctx.share_data.api_data=awaitaxios.get('/api'); awaitnext(); };
api-1.js
constapi=require('api.js'); module.exports=compose([ api, async(ctx,next)=>{ const{api_data:{api_data:{id=0}={}}={}}=ctx; if(id<0){ awaitnext(); }else{ ctx.api_data.api_1_data=awaitaxios.get('/api',{params:{id}}); } awaitnext(); }, ])
app.js
constapi_1=require('api_1.js'); constdb=require('db.js'); constsuperCompose=require('super-compose.js'); app.get('/get-api-and-db',superCompose([api_1,db]),(ctx)=>ctx.body=ctx.share_data);
跳过中间件
有时候,需要根据特定的条件,绕过某些接口调用
改造下api.js,通过加入过滤列表
module.exports=async(ctx,next)=>{ const{break_list=[]}=ctx; if(break_list.includes('api_data')){ //可能会误伤其他组合引用该中间件的情况。 //如可能会误伤,可加上。 //ctx.break_list=break_list.filter(v=>v!=='api_data') returnawaitnext(); }else{ ctx.share_data.api_data=awaitaxios.get('/api'); } awaitnext(); }
app.js
constapi=require('api.js'); constdb=require('db.js'); constsuperCompose=require('super-compose.js'); app.get( '/get-api-and-db', async(ctx,next)=>{ ctx.break_list=['api_data']; awaitnext(); }, superCompose([api,db]), ctx=>(ctx.body=ctx.share_data) );
数据合并处理
结合super-compose与koa-compose将所有需要的中间件组合起来,在写一个针对页面的controller
constapi=require('api.js'); constdb=require('db.js'); constsuperCompose=require('super-compose.js'); constcompost=rquire('koa-compose') constbabala=compose([ superCompose([api,db]), async(ctx,next)=>{ const{ share_data:{api_data:{id=0}={},db_data:{title}={}}={}, }=ctx; ctx.body={id,title}; //OR //ctx.share_data.babala={} }, ]); app.get( '/get-api-and-db', babala );
结尾
解决经常出现的一个函数内大量的接口、逻辑操作,超长的上下文逻辑。
app.get('/api',asyncctx=>{ constapi_1=awaitaxios.get('/api_1'); awaitapi_2=awaitaxios.get('/api_2'); //... //... //这里有一百行 //... const[api_3,api_4]=awaitnewPromise.all([axios.get('/api_3'),axios.get('/api_4')]); //... //... //这里有几百行 //... ctx.body={}; });
以上就是koa2数据api中间件设计模型的实现方法的详细内容,更多关于koa2中间件设计模型的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。