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 相关文章推荐
基于豆瓣API+Angular开发的web App
Jan 02 Javascript
javascript正则表达式总结
Feb 29 Javascript
【经典源码收藏】基于jQuery的项目常见函数封装集合
Jun 07 Javascript
js事件驱动机制 浏览器兼容处理方法
Jul 23 Javascript
JS基于面向对象实现的选项卡效果示例
Dec 20 Javascript
VUE JS 使用组件实现双向绑定的示例代码
Jan 10 Javascript
ECMAScript6--解构
Mar 30 Javascript
JavaScript中闭包的详解
Apr 01 Javascript
jQuery树插件zTree使用方法详解
May 02 jQuery
微信小程序使用checkbox显示多项选择框功能【附源码下载】
Dec 11 Javascript
解决linux下node.js全局模块找不到的问题
May 15 Javascript
利用JavaScript写一个简单计算器
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
简单谈谈php浮点数精确运算
2016/03/10 PHP
CodeIgniter记录错误日志的方法全面总结
2016/05/17 PHP
PHP文件上传处理案例分析
2016/10/15 PHP
Redis在Laravel项目中的应用实例详解
2017/08/11 PHP
js与jquery实时监听输入框值的oninput与onpropertychange方法
2015/02/05 Javascript
JS实现点击颜色块切换指定区域背景颜色的方法
2015/02/25 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
Bootstrap布局之栅格系统详解
2016/06/13 Javascript
Jquery和BigFileUpload实现大文件上传及进度条显示
2016/06/27 Javascript
JQuery组件基于Bootstrap的DropDownList(完整版)
2016/07/05 Javascript
JS对HTML表格进行增删改操作
2016/08/22 Javascript
vue2.0+webpack环境的构造过程
2016/11/08 Javascript
关于jQuery里prev()的简单操作代码
2017/10/27 jQuery
vue服务端渲染页面缓存和组件缓存的实例详解
2018/09/18 Javascript
使用Vuex解决Vue中的身份验证问题
2018/09/28 Javascript
简单了解常用的JavaScript 库
2020/07/16 Javascript
详解Python文本操作相关模块
2017/06/22 Python
Python实现一个简单的验证码程序
2017/11/03 Python
Tornado高并发处理方法实例代码
2018/01/15 Python
Python列表删除元素del、pop()和remove()的区别小结
2019/09/11 Python
PyTorch预训练的实现
2019/09/18 Python
安装PyInstaller失败问题解决
2019/12/14 Python
python 正则表达式参数替换实例详解
2020/01/17 Python
如何基于python实现归一化处理
2020/01/20 Python
python图形开发GUI库wxpython使用方法详解
2020/02/14 Python
简述DNS进行域名解析的过程
2013/12/02 面试题
大学生饮食配送创业计划书
2014/01/04 职场文书
应急管理培训方案
2014/06/12 职场文书
领导干部贪图享乐整改措施
2014/09/21 职场文书
2014年检验科工作总结
2014/11/22 职场文书
劳动保障个人工作总结
2015/03/04 职场文书
雨中的树观后感
2015/06/03 职场文书
生日宴会祝酒词
2015/08/10 职场文书
2016保送生自荐信范文
2016/01/29 职场文书
解析redis hash应用场景和常用命令
2021/08/04 Redis
详解Spring Security如何在权限中使用通配符
2022/06/28 Java/Android