koa2 数据api中间件设计模型的实现方法

假设所有的数据库读取,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 中间件设计模型的资料请关注我们其它相关文章!

(0)

相关推荐

  • 傻瓜式解读koa中间件处理模块koa-compose的使用

    最近需要单独使用到koa-compose这个模块,虽然使用koa的时候大致知道中间件的执行流程,但是没仔细研究过源码用起来还是不放心(主要是这个模块代码少,多的话也没兴趣去研究了). koa-compose看起来代码少,但是确实绕.闭包,递归,Promise...看了一遍脑子里绕不清楚.看了网上几篇解读文章,都是针对单行代码做解释,还是绕不清楚.最后只好采取一种傻瓜的方式: koa-compose去掉一些注释,类型校验后,源码如下: function compose (middleware) {

  • Koa日志中间件封装开发详解

    对于一个服务器应用来说,日志的记录是必不可少的,我们需要使用其记录项目程序每天都做了什么,什么时候发生过错误,发生过什么错误等等,便于日后回顾.实时掌握服务器的运行状态,还原问题场景. 日志的作用 记录服务器程序运行状态: 帮助开发者快速捕获错误,定位以及决解故障. 日志中间件开发工具log4js 在node当中没有自带的日志模块,所以需要使用第三方模块 使用模块:log4js 安装: npm i log4js -S logsjs官方文档 日志分类: 访问日志: 记录客户端对项目的访问,主要是

  • 深入解析koa之中间件流程控制

    前言 koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最近终于有空,比较深入的研究了一下koa一些原理,在这里会写一系列文章来记录一下我的学习心得和理解. 在我看来,koa最核心的函数是大名鼎鼎的co,koa正是基于这个函数实现了异步回调同步化,以及中间件流程控制.当然在这篇文章中我并不会去分析co源码,我打算在整个系列文章中,一步一步讲解如何实现

  • 详解KOA2如何手写中间件(装饰器模式)

    前言 Koa 2.x 版本是当下最流行的 NodeJS 框架, Koa 2.0 的源码特别精简,不像 Express 封装的功能那么多,所以大部分的功能都是由 Koa 开发团队(同 Express 是一家出品)和社区贡献者针对 Koa 对 NodeJS 的封装特性实现的中间件来提供的,用法非常简单,就是引入中间件,并调用 Koa 的 use 方法使用在对应的位置,这样就可以通过在内部操作 ctx 实现一些功能,我们接下来就讨论常用中间件的实现原理以及我们应该如何开发一个 Koa 中间件供自己和别

  • koa中间件核心(koa-compose)源码解读分析

    最近经常使用koa进行服务端开发,迷恋上了koa的洋葱模型,觉得这玩意太好用了.而且koa是以精简为主,没有很多集成东西,所有的东西都需按需加载,这个更是太合我胃口了哈哈哈哈. 相对与express的中间件,express的中间件使用的是串联,就像冰糖葫芦一样一个接着一个,而koa使用的V型结构(洋葱模型),这将给我们的中间件提供更加灵活的处理方式. 基于对洋葱模型的热衷,所以对koa的洋葱模型进行一探究竟,不管是koa1还是koa2的中间件都是基于koa-compose进行编写的,这种V型结构

  • koa2的中间件功能及应用示例

    最近因为开发一个自己的博客网站,学习了koa2的搭建,写了一些自己认为比较重要或需要知道的koa2中间件作用和使用场景. koa-router 路由中间件 下载 npm i koa-router 使用 普通使用方法 需要注意的是引入的koa-router是一个方法,引入后需要执行这个方法. const Koa = require('koa'); const app = new Koa(); const router = require('koa-router')(); // 配置路由url //

  • 浅谈redux, koa, express 中间件实现对比解析

    如果你有 express ,koa, redux 的使用经验,就会发现他们都有 中间件(middlewares)的概念,中间件 是一种拦截器的思想,用于在某个特定的输入输出之间添加一些额外处理,同时不影响原有操作. 最开始接触 中间件是在服务端使用 express 和 koa 的时候,后来从服务端延伸到前端,看到其在redux的设计中也得到的极大的发挥.中间件的设计思想也为许多框架带来了灵活而强大的扩展性. 本文主要对比redux, koa, express 的中间件实现,为了更直观,我会抽取出

  • node中koa中间件机制详解

    koa koa是由express原班人马打造的一个更小.更富有表现力.更健壮的web框架. 在我眼中,koa的确是比express轻量的多,koa给我的感觉更像是一个中间件框架,koa只是一个基础的架子,需要用到的相应的功能时,用相应的中间件来实现就好,诸如路由系统等.一个更好的点在于,express是基于回调来处理,至于回调到底有多么的不好,大家可以自行搜索来看.koa1基于的co库,所以koa1利用Generator来代替回调,而koa2由于node对async/await的支持,所以koa

  • 深入理解 Koa 框架中间件原理

    Node 主要用在开发 Web 应用,koa 是目前 node 里最流行的 web 框架. 在 Node 开启一个 http 服务简直易如反掌,官网 demo. const http = require("http"); const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader("Content-Type", "text/plain&quo

  • 详解express与koa中间件模式对比

    起因 最近在学习koa的使用, 由于koa是相当基础的web框架,所以一个完整的web应用所需要的东西大都以中间件的形式引入,比如koa-router, koa-view等.在koa的文档里有提到:koa的中间件模式与express的是不一样的,koa是洋葱型,express是直线型,至于为什么这样,网上很多文章并没有具体分析.或者简单的说是async/await的特性之类.先不说这种说法的对错,对于我来说这种说法还是太模糊了.所以我决定通过源码来分析二者中间件实现的原理以及用法的异同. 为了简

随机推荐