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 单选框,多选框美化代码
Aug 01 Javascript
JavaScript 闭包在封装函数时的简单分析
Nov 28 Javascript
获取select元素被选中的文本内容的js代码
Jan 29 Javascript
JavaScript数据库TaffyDB用法实例分析
Jul 27 Javascript
javascript实现base64 md5 sha1 密码加密
Sep 09 Javascript
jQuery通过写入cookie实现更换网页背景的方法
Apr 15 Javascript
JavaScript常用字符串与数组扩展函数小结
Apr 24 Javascript
轻松学习Javascript闭包
Mar 01 Javascript
js, jQuery实现全选、反选功能
Mar 08 Javascript
angular2+node.js express打包部署的实战
Jul 27 Javascript
vue项目中jsonp跨域获取qq音乐首页推荐问题
May 30 Javascript
JavaScript中MutationObServer监听DOM元素详情
Nov 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
phpMyAdmin出现无法载入 mcrypt 扩展,请检查PHP配置的解决方法
2012/03/26 PHP
用来解析.htgroup文件的PHP类
2012/09/05 PHP
php将textarea数据提交到mysql出现很多空格的解决方法
2014/12/19 PHP
thinkphp中字符截取函数msubstr()用法分析
2016/01/09 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
浅析PHP中json_encode与json_decode的区别
2020/07/15 PHP
浅谈Javascript事件处理程序的几种方式
2012/06/27 Javascript
jquery渐隐渐显的图片幻灯闪烁切换实现方法
2015/02/26 Javascript
JavaScript基础知识之方法汇总结
2016/01/24 Javascript
AngularJS 自定义过滤器详解及实例代码
2016/09/14 Javascript
微信小程序 122100版本更新问题解决方案
2016/12/22 Javascript
vue时间格式化实例代码
2017/06/13 Javascript
基于angular2 的 http服务封装的实例代码
2017/06/29 Javascript
vue2.0 路由不显示router-view的解决方法
2018/03/06 Javascript
微信小程序实现分享到朋友圈功能
2018/07/19 Javascript
Vue项目报错:Uncaught SyntaxError: Unexpected token
2018/11/10 Javascript
JavaScript事件冒泡机制原理实例解析
2020/01/14 Javascript
python动态监控日志内容的示例
2014/02/16 Python
Python中的sort()方法使用基础教程
2017/01/08 Python
利用python模拟sql语句对员工表格进行增删改查
2017/07/05 Python
python对配置文件.ini进行增删改查操作的方法示例
2017/07/28 Python
windows下python安装小白入门教程
2018/09/18 Python
Django 实现图片上传和显示过程详解
2019/07/18 Python
django数据关系一对多、多对多模型、自关联的建立
2019/07/24 Python
python 检测图片是否有马赛克
2020/12/01 Python
社区母亲节活动方案
2014/03/05 职场文书
给学校的建议书
2014/03/12 职场文书
志愿者活动总结
2014/04/28 职场文书
红色故事演讲稿
2014/05/22 职场文书
篮球比赛口号
2014/06/10 职场文书
金融管理专业求职信
2014/07/10 职场文书
教育实习指导教师评语
2014/12/31 职场文书
团员自我评价范文
2015/03/10 职场文书
道歉的话语大全
2015/05/12 职场文书
《揠苗助长》教学反思
2016/02/20 职场文书
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android