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 面向对象编程
Oct 28 Javascript
Java 正则表达式学习总结和一些小例子
Sep 13 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
Jul 10 Javascript
javascript实现瀑布流自适应遇到的问题及解决方案
Jan 28 Javascript
jQuery解决input超多的表单提交
Aug 10 Javascript
Bootstrap图片轮播组件使用实例解析
Jun 30 Javascript
微信公众平台开发教程(六)获取个性二维码的实例
Dec 02 Javascript
JavaScrpt判断一个数是否是质数的实例代码
Jun 11 Javascript
详解vue-cli 2.0配置文件(小结)
Jan 14 Javascript
vue项目中使用scss的方法步骤
May 16 Javascript
微信小程序 自定义复选框实现代码实例
Sep 04 Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
Nov 03 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数组操作汇总 php数组的使用技巧
2011/07/17 PHP
PHP生成自定义长度随机字符串的函数分享
2014/05/04 PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
2019/05/29 PHP
jquery json 实例代码
2010/12/02 Javascript
JavaScript 学习笔记之一jQuery写法图片等比缩放以及预加载
2012/06/28 Javascript
jquery中JSON的解析方式
2015/03/16 Javascript
Function.prototype.apply()与Function.prototype.call()小结
2016/04/27 Javascript
JavaScript必知必会(三) String .的方法来自何方
2016/06/08 Javascript
微信小程序图片轮播组件gallery slider使用方法详解
2018/01/31 Javascript
Vue2.0 http请求以及loading展示实例
2018/03/06 Javascript
JavaScript事件对象event用法分析
2018/07/27 Javascript
JavaScript实现的DOM绘制柱状图效果示例
2018/08/08 Javascript
前端vue-cli项目中使用img图片和background背景图的几种方法
2019/11/13 Javascript
微信小程序动态设置图片大小的方法
2019/11/21 Javascript
Python 自动补全(vim)
2014/11/30 Python
pandas筛选某列出现编码错误的解决方法
2018/11/07 Python
django小技巧之html模板中调用对象属性或对象的方法
2018/11/30 Python
Django框架自定义session处理操作示例
2019/05/27 Python
python利用多种方式来统计词频(单词个数)
2019/05/27 Python
Python中的正则表达式与JSON数据交换格式
2019/07/03 Python
Python 变量的创建过程详解
2019/09/02 Python
Pandas中DataFrame基本函数整理(小结)
2020/07/20 Python
css3 position fixed固定居中问题解决方案
2014/08/19 HTML / CSS
关于box-sizing的全面理解
2016/07/28 HTML / CSS
使用html5实现表格实现标题合并的实例代码
2019/05/13 HTML / CSS
医学专业个人求职自荐信格式
2013/09/23 职场文书
生物制药毕业生自荐信
2013/10/16 职场文书
网上开店必备创业计划书
2014/01/26 职场文书
法律六进活动方案
2014/03/13 职场文书
好书伴我成长演讲稿
2014/05/14 职场文书
优秀求职信
2014/05/29 职场文书
基层党员四风问题自我剖析材料
2014/09/29 职场文书
不尊敬老师检讨书范文
2014/11/19 职场文书
2015年电厂工作总结范文
2015/05/13 职场文书
Canvas跟随鼠标炫彩小球的实现
2021/04/11 Javascript
Vue中Object.assign清空数据报错的解决方案
2022/03/03 Vue.js