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 相关文章推荐
prototype 1.5相关知识及他人笔记
Dec 16 Javascript
Javascript YUI 读码日记之 YAHOO.util.Dom - Part.2 0
Mar 22 Javascript
简单的Jquery全选功能
Nov 07 Javascript
JavaScript实现维吉尼亚(Vigenere)密码算法实例
Nov 22 Javascript
javascript打开word文档的方法
Apr 16 Javascript
用svg制作富有动态的tooltip
Jul 17 Javascript
使用AmplifyJS组件配合JavaScript进行编程的指南
Jul 28 Javascript
javascript实现随机读取数组的方法
Aug 03 Javascript
javascript实现获取图片大小及图片等比缩放的方法
Nov 24 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
Dec 08 Javascript
BootStrap Table 设置height表头与内容无法对齐的问题
Dec 28 Javascript
对angular2中的ngfor和ngif指令嵌套实例讲解
Sep 12 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
支持oicq头像的留言簿(一)
2006/10/09 PHP
PHP 输出URL的快捷方式示例代码
2013/09/22 PHP
php和nginx交互实例讲解
2019/09/24 PHP
在线编辑器的实现原理(兼容IE和FireFox)
2007/03/09 Javascript
jquery特效 幻灯片效果示例代码
2013/07/16 Javascript
浅析JQuery中的html(),text(),val()区别
2014/09/01 Javascript
jQuery不兼容input的change事件问题解决过程
2014/12/05 Javascript
JS实现网页背景颜色与select框中颜色同时变化的方法
2015/02/27 Javascript
理解Javascript的call、apply
2015/12/16 Javascript
基于jQuery实现音乐播放试听列表
2016/04/14 Javascript
JavaScript中的Array 对象(数组对象)
2016/06/02 Javascript
JavaScript中instanceof运算符的使用示例
2016/06/08 Javascript
javascript深拷贝和浅拷贝详解
2017/02/14 Javascript
React diff算法的实现示例
2018/04/20 Javascript
使用vue-router与v-if实现tab切换遇到的问题及解决方法
2018/09/07 Javascript
Nodejs模块的调用操作实例分析
2018/12/25 NodeJs
[03:01]DOTA2英雄基础教程 露娜
2014/01/07 DOTA
Python实现扫描指定目录下的子目录及文件的方法
2014/07/16 Python
python版本的仿windows计划任务工具
2018/04/30 Python
opencv python 傅里叶变换的使用
2018/07/21 Python
python的pygal模块绘制反正切函数图像方法
2019/07/16 Python
python代码能做成软件吗
2020/07/24 Python
python3:excel操作之读取数据并返回字典 + 写入的案例
2020/09/01 Python
爬虫代理的cookie如何生成运行
2020/09/22 Python
CSS3实现时间轴效果
2016/07/11 HTML / CSS
英国和世界各地鲜花速递专家:Arena Flowers
2018/02/10 全球购物
买卖正宗运动鞋:GOAT
2019/12/06 全球购物
国际花店:Pickup Flowers
2020/04/10 全球购物
美国乒乓球设备、配件和服装品牌:Killerspin
2020/06/07 全球购物
婚庆公司计划书
2014/09/15 职场文书
收入证明申请书
2015/06/12 职场文书
2016感恩母亲节校园广播稿
2015/12/17 职场文书
浅谈哪个Python库才最适合做数据可视化
2021/06/28 Python
微信小程序APP的事件绑定以及传递参数时的冒泡和捕获
2022/04/19 Javascript
Win10 Anaconda安装python-pcl
2022/04/29 Servers
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL