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 相关文章推荐
javascript一点特殊用法
May 28 Javascript
父元素与子iframe相互获取变量和元素对象的具体实现
Oct 15 Javascript
php+js实现倒计时功能
Jun 02 Javascript
jQuery中parent()方法用法实例
Jan 07 Javascript
js控制输入框获得和失去焦点时状态显示的方法
Jan 30 Javascript
深入理解JavaScript系列(37):设计模式之享元模式详解
Mar 04 Javascript
Java Mybatis框架入门基础教程
Sep 21 Javascript
JavaScript实现的MD5算法完整实例
Feb 02 Javascript
jQuery Mobile动态刷新页面样式的实现方法
May 28 Javascript
微信小程序 Storage API实例详解
Oct 02 Javascript
jquery 判断是否支持Placeholder属性的方法
Feb 07 Javascript
vue父组件中获取子组件中的数据(实例讲解)
Sep 27 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下使用无限生命期Session的方法
2007/03/16 PHP
PHP chmod 函数与批量修改文件目录权限
2010/05/10 PHP
Prototype中dom对象方法汇总
2008/09/17 Javascript
javascript div 遮罩层封锁整个页面
2009/07/10 Javascript
jQuery第三课 修改元素属性及内容的代码
2010/03/14 Javascript
js实现拖拽 闭包函数详细介绍
2012/11/25 Javascript
IE8下Jquery获取select选中的值post到后台报错问题
2014/07/02 Javascript
javascript实现跨域的方法汇总
2015/06/25 Javascript
JavaScript继承学习笔记【新手必看】
2016/05/10 Javascript
JavaScript仿微博输入框效果(案例分析)
2016/12/06 Javascript
vue分类筛选filter方法简单实例
2017/03/30 Javascript
JS+canvas画一个圆锥实例代码
2017/12/13 Javascript
微信小程序实现跳转的几种方式总结(推荐)
2019/04/24 Javascript
浅谈Vue SSR中的Bundle的具有使用
2019/11/21 Javascript
React中Ref 的使用方法详解
2020/04/28 Javascript
微信小程序语音同步智能识别的实现案例代码解析
2020/05/29 Javascript
详解python的数字类型变量与其方法
2016/11/20 Python
python skimage 连通性区域检测方法
2018/06/21 Python
python实现身份证实名认证的方法实例
2019/11/08 Python
python3获取控制台输入的数据的具体实例
2020/08/16 Python
python 利用百度API识别图片文字(多线程版)
2020/12/14 Python
详解Canvas事件绑定
2018/06/27 HTML / CSS
美国儿童玩具、装扮和玩偶商店:Magic Cabin
2018/09/02 全球购物
static函数与普通函数有什么区别
2015/12/25 面试题
车辆安全检查制度
2014/01/12 职场文书
《恐龙》教学反思
2014/04/27 职场文书
新学期标语
2014/06/30 职场文书
公司收款委托书范本
2014/09/20 职场文书
2014党委书记四风对照检查材料思想汇报
2014/09/21 职场文书
工作迟到检讨书范文
2015/05/06 职场文书
超市员工辞职信范文
2015/05/12 职场文书
毕业论文致谢范文
2015/05/14 职场文书
入党函调证明材料
2015/06/19 职场文书
珍爱生命主题班会
2015/08/13 职场文书
详解分布式系统中如何用python实现Paxos
2021/05/18 Python
python使用pycharm安装pyqt5以及相关配置
2022/04/22 Python