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 代码集(学习js的朋友可以看下)
Jul 22 Javascript
动态生成的DOM不会触发onclick事件的原因及解决方法
Aug 06 Javascript
jQuery实现导航高亮的方法【附demo源码下载】
Nov 09 Javascript
有关suggest快速删除后仍然出现下拉列表的bug问题
Dec 02 Javascript
你不知道的 javascript【推荐】
Jan 08 Javascript
javascript获取以及设置光标位置
Feb 16 Javascript
JavaScript使用atan2来绘制箭头和曲线的实例
Sep 14 Javascript
详解设置Webstorm 利用babel将ES6自动转码成ES5
Dec 20 Javascript
详解使用VUE搭建后台管理系统(vue-cli更新至3.0)
Aug 22 Javascript
在移动端使用vue-router和keep-alive的方法示例
Dec 02 Javascript
深入了解JavaScript 防抖和节流
Sep 12 Javascript
微信接入之获取用户头像的方法步骤
Sep 23 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录入页面中动态从数据库中提取数据的实现
2006/10/09 PHP
PHP 加密/解密函数 dencrypt(动态密文,带压缩功能,支持中文)
2009/01/30 PHP
基于ThinkPHP+uploadify+upload+PHPExcel 无刷新导入数据
2015/09/23 PHP
php 升级到 5.3+ 后出现的一些错误,如 ereg(); ereg_replace(); 函数报错
2015/12/07 PHP
Yii2框架引用bootstrap中日期插件yii2-date-picker的方法
2016/01/09 PHP
php实现留言板功能
2017/03/05 PHP
js parseInt(&quot;08&quot;)未指定进位制问题
2010/06/19 Javascript
Jquery中给animation加更多的运作效果实例
2013/09/05 Javascript
JS保存和删除cookie操作 判断cookie是否存在
2013/11/13 Javascript
jQuery实现dialog设置focus焦点的方法
2015/06/10 Javascript
正则验证小数点后面只能有两位数的方法
2017/02/28 Javascript
Angular2搜索和重置按钮过场动画
2017/05/24 Javascript
jQuery使用ajax_动力节点Java学院整理
2017/07/05 jQuery
vue+echarts实现动态绘制图表及异步加载数据的方法
2018/10/17 Javascript
Vue使用NProgress的操作过程解析
2019/10/10 Javascript
javascript实现简单留言板案例
2021/02/09 Javascript
[02:09:59]火猫TV国士无双dota2 6.82版本详解(下)
2014/09/29 DOTA
Python脚本在Appium库上对移动应用实现自动化测试
2015/04/17 Python
Flask框架的学习指南之制作简单blog系统
2016/11/20 Python
Python程序运行原理图文解析
2018/02/10 Python
对python 读取线的shp文件实例详解
2018/12/22 Python
在Python文件中指定Python解释器的方法
2019/02/18 Python
pandas中遍历dataframe的每一个元素的实现
2019/10/23 Python
pytorch实现focal loss的两种方式小结
2020/01/02 Python
python连接mongodb数据库操作数据示例
2020/11/30 Python
详解Pycharm第三方库的安装及使用方法
2020/12/29 Python
浅析CSS3 用text-overflow解决文字排版问题
2020/10/28 HTML / CSS
Topshop美国官网:英国快速时尚品牌
2019/05/16 全球购物
如何防止同一个帐户被多人同时登录
2013/08/01 面试题
人力资源部经理助理岗位职责
2014/03/04 职场文书
小学学习雷锋活动总结
2014/07/03 职场文书
民主评议党员登记表自我评价
2014/10/20 职场文书
2014年精神文明工作总结
2014/12/23 职场文书
工作失职检讨书
2015/01/26 职场文书
西安大雁塔导游词
2015/02/10 职场文书
高中班主任培训心得体会
2016/01/07 职场文书