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 优化次数过多的循环 考虑到性能问题
Mar 05 Javascript
javascript开发随笔二 动态加载js和文件
Nov 25 Javascript
js opener的使用详解
Jan 11 Javascript
jquery 操作css样式、位置、尺寸方法汇总
Nov 28 Javascript
jQuery的one()方法用法实例
Jan 19 Javascript
js实现固定显示区域内自动缩放图片的方法
Jul 18 Javascript
AngularJS 让人爱不释手的八种功能
Mar 23 Javascript
Node.js设置CORS跨域请求中多域名白名单的方法
Mar 28 Javascript
mac上配置Android环境变量的方法
Jul 08 Javascript
JSX在render函数中的应用详解
Sep 04 Javascript
VUE+node(express)实现前后端分离
Oct 13 Javascript
基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能
Jan 05 Vue.js
浅析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中限制ip段访问、禁止ip提交表单的代码分享
2014/08/22 PHP
PHP获取数组最后一个值的2种方法
2015/01/21 PHP
PHP代码维护,重构变困难的4种原因分析
2016/01/25 PHP
PHP5.4起内置web服务器使用方法
2016/08/09 PHP
Yii2汉字转拼音类的实例代码
2017/04/18 PHP
记录Yii2框架开发微信公众号遇到的问题及解决方法
2018/07/20 PHP
PHP多个图片压缩成ZIP的方法
2020/08/18 PHP
javascript中的几个运算符
2007/06/29 Javascript
FormValidate 表单验证功能代码更新并提供下载
2008/08/23 Javascript
JavaScript 打地鼠游戏代码说明
2010/10/12 Javascript
js 去除字符串第一位逗号的方法
2014/06/07 Javascript
JavaScript实现自动对页面上敏感词进行屏蔽的方法
2015/07/27 Javascript
jquery控制显示服务器生成的图片流
2015/08/04 Javascript
JavaScript学习笔记之函数记忆
2017/09/06 Javascript
详解VUE 对element-ui中的ElTableColumn扩展
2018/03/28 Javascript
javascript实现文件拖拽事件
2018/03/29 Javascript
手把手教你写一个微信小程序(推荐)
2018/10/17 Javascript
7个好用的JavaScript技巧分享(译)
2019/05/07 Javascript
nodejs实现UDP组播示例方法
2019/11/04 NodeJs
Vue实现渲染数据后控制滚动条位置(推荐)
2019/12/09 Javascript
jQuery中getJSON跨域原理的深入讲解
2020/09/02 jQuery
基于react项目打包css引用路径错误解决方案
2020/10/28 Javascript
一步步教你用Python实现2048小游戏
2017/01/19 Python
在双python下设置python3为默认的方法
2018/10/31 Python
python退出命令是什么?详解python退出方法
2018/12/10 Python
利用python为PostgreSQL的表自动添加分区
2021/01/18 Python
python爬虫beautifulsoup库使用操作教程全解(python爬虫基础入门)
2021/02/19 Python
html5 利用canvas实现超级玛丽简单动画
2013/09/06 HTML / CSS
Stuart Weitzman美国官网:美国奢华鞋履品牌
2016/08/18 全球购物
怎样让char类型的东西转换成int类型
2013/12/09 面试题
网站设计师的岗位职责
2013/11/21 职场文书
十佳标兵事迹材料
2014/08/18 职场文书
邀请函样本
2015/02/02 职场文书
html+css 实现简易导航栏功能
2021/04/07 HTML / CSS
Golang并发操作中常见的读写锁详析
2021/08/30 Golang
Go web入门Go pongo2模板引擎
2022/05/20 Golang