koa2 数据api中间件设计模型的实现方法


Posted in Javascript onJuly 13, 2020

假设所有的数据库读取,http api 接口请求都为一个中间件,将中间件当做插件,插入需要获取数据的位置。

api.js

module.exports = async (ctx, next) => {
 ctx.share_data.api_data = await axios.get('/api');

 await next();
};

db.js

module.exports = async (ctx, next) => {
 ctx.share_data.db_data = await mysql_query('SELECT XXX').catch(() => {});

 await next();
};

串联

app.js

const api = require('api.js');
const db = 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)) throw new TypeError('Middleware stack must be an array!');
 for (const fn of middleware) {
  if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!');
 }

 return async (context = {}, next = f => f) => {
  await Promise.all(
   middleware.map(middleware => {
    return new Promise((rs, rj) => {
     middleware(context, () => Promise.resolve())
      .then(rs)
      .catch(rj);
    });
   }),
  );

  await next();
 };
};

app.js

const api = require('api.js');
const db = require('db.js');
const superCompose = 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) {
  return await next();
 }

 ctx.share_data.api_data = await axios.get('/api');

 await next();
};

api-1.js

const api = require('api.js');

module.exports = compose([
 api,
 async (ctx, next) => {
  const { api_data: { api_data: { id = 0 } = {} } = {} } = ctx;

  if (id < 0) {
   await next();
  } else {
   ctx.api_data.api_1_data = await axios.get('/api', { params: { id } });
  }

  await next();
 },
])

app.js

const api_1 = require('api_1.js');
const db = require('db.js');
const superCompose = 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')
  return await next();
 } else {
  ctx.share_data.api_data = await axios.get('/api');
 }

 await next();
}

app.js

const api = require('api.js');
const db = require('db.js');
const superCompose = require('super-compose.js');
          
app.get(
 '/get-api-and-db',
 async (ctx, next) => {
  ctx.break_list = ['api_data'];
  await next();
 },
 superCompose([api, db]),
 ctx => (ctx.body = ctx.share_data)
);

数据合并处理

结合 super-compose 与 koa-compose 将所有需要的中间件组合起来,在写一个针对页面的controller

const api = require('api.js');
const db = require('db.js');
const superCompose = require('super-compose.js');
const compost = rquire('koa-compose')

const babala = 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', async ctx => {
 const api_1 = await axios.get('/api_1');
 await api_2 = await axios.get('/api_2');

 // ...
 // ...
 // 这里有一百行
 // ... 
 
 const [api_3, api_4] = await new Promise.all([axios.get('/api_3'), axios.get('/api_4')]);
 
 // ...
 // ...
 // 这里有几百行
 // ...

 ctx.body = {};
});

以上就是koa2 数据api中间件设计模型的实现方法的详细内容,更多关于koa2 中间件设计模型的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
在网页中屏蔽快捷键
Sep 06 Javascript
关于恒等于(===)和非恒等于(!==)
Aug 20 Javascript
jquery子元素过滤选择器使用示例
Jun 24 Javascript
javascript事件函数中获得事件源的两种不错方法
Mar 17 Javascript
jQuery中 delegate使用的问题
Jul 03 Javascript
jQuery实现的经典滑动门效果
Sep 22 Javascript
Jquery 效果使用详解
Nov 23 Javascript
jQuery UI插件实现百度提词器效果
Nov 21 Javascript
原生js实现无限循环轮播图效果
Jan 20 Javascript
vuejs使用$emit和$on进行组件之间的传值的示例
Oct 04 Javascript
js实现复制功能(多种方法集合)
Jan 06 Javascript
javascript Canvas动态粒子连线
Jan 01 Javascript
浅析JavaScript 函数防抖和节流
Jul 13 #Javascript
详解JavaScript 异步编程
Jul 13 #Javascript
javascript canvas时钟模拟器
Jul 13 #Javascript
微信小程序整个页面的自动适应布局的实现
Jul 12 #Javascript
uniapp 仿微信的右边下拉选择弹出框的实现代码
Jul 12 #Javascript
微信小程序实现列表滚动头部吸顶的示例代码
Jul 12 #Javascript
Js on及addEventListener原理用法区别解析
Jul 11 #Javascript
You might like
Terran剧情介绍
2020/03/14 星际争霸
php中通过curl smtp发送邮件
2012/06/05 PHP
php统计时间和内存使用情况示例分享
2014/03/13 PHP
php中try catch捕获异常实例详解
2014/11/21 PHP
php设置页面超时时间解决方法
2015/09/22 PHP
yii2.0实现pathinfo的形式访问的配置方法
2016/04/06 PHP
PDO::getAvailableDrivers讲解
2019/01/28 PHP
JSQL 基于客户端的成绩统计实现方法
2010/05/05 Javascript
利用webqq协议使用python登录qq发消息源码参考
2013/04/08 Javascript
angularjs表格ng-table使用备忘录
2016/03/09 Javascript
移动端手指放大缩小插件与js源码
2017/05/22 Javascript
详解JavaScript数组过滤相同元素的5种方法
2017/05/23 Javascript
基于JavaScript实现弹幕特效
2020/08/27 Javascript
javascript编程开发中取色器及封装$函数用法示例
2017/08/09 Javascript
Vue 一键清空表单的实现方法
2020/02/07 Javascript
基于Vue CSR的微前端实现方案实践
2020/05/27 Javascript
JS实现数据动态渲染的竖向步骤条
2020/06/24 Javascript
Vue和React有哪些区别
2020/09/12 Javascript
[06:53]2018DOTA2国际邀请赛寻真——勇于创新的Vici Gaming
2018/08/14 DOTA
python监控网卡流量并使用graphite绘图的示例
2014/04/27 Python
Python高级应用实例对比:高效计算大文件中的最长行的长度
2014/06/08 Python
python使用sorted函数对列表进行排序的方法
2015/04/04 Python
python使用xslt提取网页数据的方法
2018/02/23 Python
Python实现统计给定字符串中重复模式最高子串功能示例
2018/05/16 Python
python3模拟实现xshell远程执行liunx命令的方法
2019/07/12 Python
在SQLite-Python中实现返回、查询中文字段的方法
2019/07/17 Python
Python3如何使用多线程升程序运行速度
2020/08/11 Python
Python 连接 MySQL 的几种方法
2020/09/09 Python
pycharm专业版远程登录服务器的详细教程
2020/09/15 Python
俄罗斯购买自行车网站:Vamvelosiped
2021/01/29 全球购物
网络教育毕业生自我鉴定
2013/10/10 职场文书
2014年医学生毕业自我鉴定
2014/03/26 职场文书
校长竞聘演讲稿
2014/05/16 职场文书
2014年小班保育员工作总结
2014/12/23 职场文书
创业计划书之熟食店
2019/10/16 职场文书
Python如何解决secure_filename对中文不支持问题
2021/07/16 Python