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 相关文章推荐
Ubuntu 11.10 安装Node.js的方法
Nov 30 Javascript
JavaScript中的数组特性介绍
Dec 30 Javascript
触屏中的JavaScript事件分析
Feb 06 Javascript
原创jQuery弹出层插件分享
Apr 02 Javascript
js中常用的Tab切换效果(推荐)
Aug 30 Javascript
使用jQuery的load方法设计动态加载及解决被加载页面js失效问题
Mar 01 Javascript
Angular2 之 路由与导航详细介绍
May 26 Javascript
详解如何用VUE写一个多用模态框组件模版
Sep 27 Javascript
jQuery实现购物车的总价计算和总价传值功能
Nov 28 jQuery
JavaScript中的ES6 Proxy的具体使用
Jun 16 Javascript
jquery 插件重新绑定的处理方法分析
Nov 23 jQuery
微信小程序去除左上角返回键的实现方法
Mar 06 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 empty函数 使用说明
2009/08/10 PHP
详解PHP对象的串行化与反串行化
2016/01/24 PHP
PHP一个简单的无需刷新爬虫
2019/01/05 PHP
XmlUtils JS操作XML工具类
2009/10/01 Javascript
js中匿名函数的N种写法
2010/09/08 Javascript
Javascript获取HTML静态页面参数传递值示例
2013/08/18 Javascript
2014 HTML5/CSS3热门动画特效TOP10
2014/12/07 Javascript
超级简单实现JavaScript MVC 样式框架
2015/03/24 Javascript
jQuery使用CSS()方法给指定元素同时设置多个样式
2015/03/26 Javascript
js数组去重的方法汇总
2015/07/29 Javascript
Bootstrap中的表单验证插件bootstrapValidator使用方法整理(推荐)
2016/06/21 Javascript
IE下JS保存图片的简单实例
2016/07/15 Javascript
javaScript基础详解
2017/01/19 Javascript
简单易懂的天气插件(代码分享)
2017/02/04 Javascript
关于laydate.js加载laydate.css路径错误问题解决
2017/12/27 Javascript
详解如何构建Promise队列实现异步函数顺序执行
2018/10/23 Javascript
vue 移动端适配方案详解
2018/11/15 Javascript
node和vue实现商城用户地址模块
2018/12/05 Javascript
微信小程序获取地理位置及经纬度授权代码实例
2019/09/18 Javascript
浅谈Vue中render中的h箭头函数
2019/11/07 Javascript
[02:47]2018年度DOTA2最佳辅助位选手4号位-完美盛典
2018/12/17 DOTA
kali中python版本的切换方法
2019/07/11 Python
python list转置和前后反转的例子
2019/08/26 Python
python3 实现调用串口功能
2019/12/26 Python
Python使用monkey.patch_all()解决协程阻塞问题
2020/04/15 Python
Python制作运行进度条的实现效果(代码运行不无聊)
2021/02/24 Python
UGG雪地靴德国官网:UGG德国
2016/11/19 全球购物
英国领先的运动物理治疗供应公司:Vivomed
2018/07/14 全球购物
澳大利亚墨水站Ink Station:墨水和碳粉打印机墨盒
2019/03/24 全球购物
德国玩具商店:Planet Happy DE
2021/01/16 全球购物
网络工程师个人的自我评价范文
2013/10/01 职场文书
领导调研接待方案
2014/02/27 职场文书
金融管理专业求职信
2014/07/10 职场文书
人事行政专员岗位职责
2014/07/23 职场文书
给校长的一封检讨书
2014/09/20 职场文书
2015年实习单位评语
2015/03/25 职场文书