node 中间件使用例子

NodeJS在中间件领域有着较为广泛的应用,他能做一些中间层事件,把服务端一部分的代码抽出来,减少处理冗余事情付出的代价,同时让服务真正做业务处理而不用关心页面的事情

常见的应用场景有:

  1. 跨域:解决跨域问题,前端不需要任何相关配置(当然这部分代码可以放在服务端)

  2. 数据mock:前后端同步开发(这没什么好说的)

  3. 接口整合或拆分:中间层的功能是作为后端接口与客户端界面之间的桥梁。前端首先向中间层发起请求,中间层根据业务逻辑向指定后端服务发起请求,后端返回数据后, 中间层根据前端所需的数据格式、种类进行排序筛选等整合封装,最后返回给前端。

  4. 代理:在开发环境下,可以利用Node.js代理,解决最常见的跨域问题;在线上环境下,我们可以利用代理,转发请求到多个服务端,起到类似于Nginx的负载均衡作用,且Node.js中可以很方便的根据业务架构编写转发逻辑代码,相对Ngnix更加灵活。

  5. 缓存:缓存其实是更靠近前端的需求,用户的动作触发数据的更新,Node.js中间层可以直接处理一部分缓存需求,在Redis中获取热点数据或临时数据。而不需要再去请求后端和数据库。 - 限流:Node.js中间层里,可以针对接口或者路由做响应的限流逻辑开发。

  6. 限流:Node.js中间层里,可以针对接口或者路由做响应的限流逻辑开发。

  7. 日志:相比其他服务端语言,Node.js中间层的日志记录,能更方便快捷的定位问题系统问题是后台服务还是前端问题。

  8. 监控:利用Node.js擅长高并发的请求处理的特性,可以用来做服务流量监控入口监控。

  9. 鉴权:微服务架构加可以将身份认证,权限校验的功能统一提前到中间层,不需要在每个服务里都对请求鉴权,降低代码冗余。此外也可以在Node.js中实现针对不同用户转发到不同后端服务的逻辑,这也是灰度发布的一种实现方式。

  10. 路由:前端更需要掌握页面路由的权限和逻辑,在中间层中对接口数据、路由整合转发,可以实现前端路由和请求接口路由的一致性,而后端服务接口路由可以独立设计,不需要迁就某个客户端所需的路由。

我写了一个demo加深理解,首先解释一下代码目录

代码地址:github地址

看app.js

日志中间件
复制代码
// 日志中间件
app.use(async (ctx, next) => {
  const start = new Date();
  let ms;
  try {
    await next();
    ms = new Date() - start;
    logger.accessLog(ctx, ms);
  } catch (error) {
    ms = new Date() - start;
    logger.errorLog(ctx, error, ms);
  }
});

每次请求都会往文件输出一条日志方便查找错误,使用的是npm包---log4js,具体封装见/src/logs/logs.js

跨域中间件
复制代码
// middlewares
app.use(KoaCors())
body解析中间件
复制代码
//body解析中间件
app.use(bodyParser())
路由中间件
复制代码
import KoaRouter from '@koa/router'
//路由中间间,routers 是导出的函数
app.use(router.routes()).use(router.allowedMethods());

routers(router)

代码所有的目录入口都是index

复制代码
import requireIndex from 'es6-requireindex'
import middleswares from '../middlewares';
const controller = require('../controllers');
const modulesFiles = requireIndex(__dirname).modules;
export default (router) => {
  Object.keys(modulesFiles).forEach((item) => {
    modulesFiles[item](router, middleswares, controller)
  })
}

目的是为了配合koa的洋葱模型,

举个例子:

复制代码
 router.get('/department/list', middleswares.formatBody, controller.department.list);

在处理完路由之后先通过controller处理,然后执行formatBody,再把结果返回,所以写这个回调函数的时候要特别注意

复制代码
/**
 * 响应数据格式化输出中间件
 * 
 */

module.exports = async (ctx, next) => {
  try {
    await next();//执行路由 这个next函数就是控制器函数,意思先执行处理逻辑,把结果根据自己的格式返回
    if (ctx.body) {
      ctx.body = {
        code: ctx.response.status,
        success: true,
        message: 'success',
        data: ctx.body
      }
    } else {
      ctx.body = {
        code: ctx.response.status,
        success: true,
        message: 'success',
      }
    }
  } catch (err) {
    console.log(err);
    ctx.response.status = err.response.status;
    ctx.body = {
      success: false,
      message: err.response.data.text,
    };
  }
}

不需要经过中间件处理的就写成这样就可以

复制代码
  router.get('/user', controller.login.userInfo);
相关推荐
大怪v1 小时前
【Virtual World 04】我们的目标,无限宇宙!!
前端·javascript·代码规范
狂炫冰美式1 小时前
不谈技术,搞点文化 🧀 —— 从复活一句明代残诗破局产品迭代
前端·人工智能·后端
muxin-始终如一2 小时前
消息丢失场景和解决方案
数据库·中间件·消息丢失
xw52 小时前
npm几个实用命令
前端·npm
!win !2 小时前
npm几个实用命令
前端·npm
代码狂想家2 小时前
使用openEuler从零构建用户管理系统Web应用平台
前端
dorisrv4 小时前
优雅的React表单状态管理
前端
蓝瑟4 小时前
告别重复造轮子!业务组件多场景复用实战指南
前端·javascript·设计模式
dorisrv4 小时前
高性能的懒加载与无限滚动实现
前端
韭菜炒大葱4 小时前
别等了!用 Vue 3 让 AI 边想边说,字字蹦到你脸上
前端·vue.js·aigc