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 相关文章推荐
js调用后台servlet方法实例
Jun 09 Javascript
基于jquery实现一张图片点击鼠标放大再点缩小
Sep 29 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
Feb 11 Javascript
简述Matlab中size()函数的用法
Mar 20 Javascript
JS简单实现仿百度控制台输出信息效果
Sep 04 Javascript
详解Jquery Easyui的验证扩展
Jan 09 Javascript
angular2中Http请求原理与用法详解
Jan 11 Javascript
Vue中遍历数组的新方法实例详解
Jul 21 Javascript
JavaScript 面向对象程序设计详解【类的创建、实例对象、构造函数、原型等】
May 12 Javascript
简单了解three.js 着色器材质
Aug 03 Javascript
我所理解的JavaScript中的this指向
Sep 04 Javascript
JavaScript小技巧带你提升你的代码技能
Sep 15 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
php获取远程图片的两种 CURL方式和sockets方式获取远程图片
2011/11/07 PHP
php中XMLHttpRequest(Ajax)不能设置自定义的Referer的解决方法
2011/11/26 PHP
PHP关联链接常用代码
2012/11/05 PHP
PHP 只允许指定IP访问(允许*号通配符过滤IP)
2014/07/08 PHP
PHP中子类重载父类的方法【parent::方法名】
2016/05/06 PHP
PHP排序算法之归并排序(Merging Sort)实例详解
2018/04/21 PHP
PHP实现小程序批量通知推送
2018/11/27 PHP
TNC vs BOOM BO3 第一场2.13
2021/03/10 DOTA
用JS剩余字数计算的代码
2008/07/03 Javascript
javascript instanceof 与typeof使用说明
2010/01/11 Javascript
js实现遮罩层划出效果是生成div而不是显示
2014/07/29 Javascript
JavaScript的jQuery库中ready方法的学习教程
2015/08/14 Javascript
Jquery中巧用Ajax的beforeSend方法
2016/01/20 Javascript
JS实现根据用户输入分钟进行倒计时功能
2016/11/14 Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
2017/06/04 Javascript
基于JavaScript实现选项卡效果
2017/07/21 Javascript
vue-cli webpack模板项目搭建及打包时路径问题的解决方法
2018/02/26 Javascript
AngularJS日期格式化常见操作实例分析
2018/05/17 Javascript
深度了解vue.js中hooks的相关知识
2019/06/14 Javascript
微信小程序事件 bindtap bindinput代码实例
2019/08/26 Javascript
vue服务端渲染操作简单入门实例分析
2019/08/28 Javascript
Python排序搜索基本算法之插入排序实例分析
2017/12/11 Python
python和opencv实现抠图
2018/07/18 Python
python 实现让字典的value 成为列表
2019/12/16 Python
开启Django博客的RSS功能的实现方法
2020/02/17 Python
解决python cv2.imread 读取中文路径的图片返回为None的问题
2020/06/02 Python
阿尔卡特(中国)的面试题目
2014/08/20 面试题
2013年办公室秘书的个人自我鉴定
2013/10/24 职场文书
汉语言文学毕业生自荐信范文
2014/03/24 职场文书
倡议书范文格式
2014/05/12 职场文书
监督检查工作方案
2014/05/28 职场文书
化工专业求职信
2014/07/01 职场文书
世界地球日活动总结
2015/02/09 职场文书
个人总结与自我评价
2015/02/14 职场文书
普希金的诗歌赏析(3首)
2019/08/20 职场文书
mysql知识点整理
2021/04/05 MySQL