手记

【九月打卡】第21天 eggjs 插件、middleware

课程名称:web前端架构师

课程章节:第14周 第三章、第四章

主讲老师:张轩

课程内容: eggjs 插件和中间键

egg 插件

插件机制 是egg 的一大特色。它不但可以保证框架核心的足够精简、稳定、高效,还可以促进业务逻辑的复用,生态圈的形成。

为什么要插件

我们在使用 Koa 中间件过程中发现了下面一些问题:

  • 中间件加载其实是有先后顺序的,但是中间件自身却无法管理这种顺序,只能交给使用者。这样其实非常不友好,一旦顺序不对,结果可能有天壤之别。
  • 中间件的定位是拦截用户请求,并在它前后做一些事情,例如:鉴权、安全检查、访问日志等等。但实际情况是,有些功能是和请求无关的,例如:定时任务、消息订阅、后台逻辑等等。
  • 有些功能包含非常复杂的初始化逻辑,需要在应用启动的时候完成。这显然也不适合放到中间件中去实现。

综上所述,我们需要一套更加强大的机制,来管理、编排那些相对独立的业务逻辑。

使用插件

比如我们要使用 ejs 模版渲染插件

npm i egg-plugin-ejs

在 config/plugin.ts 添加

const plugin: EggPlugin = {
  ejs: {
    enable: true,
    package: 'egg-view-ejs',
  },
};

修改 config/config.default.ts

config.view = {
  mapping: {
    '.ejs': 'ejs',
  },
};

编写 view 文件

// app/view/dog.ejs
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%=title%></title>
</head>
<body>
  <img src="<%=url%>"/>
</body>
</html>

修改 controller

import { Controller } from 'egg';
export default class DogController extends Controller {
  async dog() {
    const { service, ctx } = this;
    const res = await service.dog.show<{
      message: string
      status: string
    }>();
    // 渲染 eje 文件
    await ctx.render('dog.ejs', {
      url: res.message,
      title: 'Dog',
    });
  }
}

middleweare

手写一个中间键

中间键放在 app/middleware 目录下
新建一个文件logger.ts

import { Context } from 'egg';
import { appendFileSync } from 'fs';
export default () => {
  return async (ctx: Context, next: () => Promise<any>) => {
    const startTime = Date.now();
    await next();
    appendFileSync('./log.txt', `time: ${Date.now() - startTime} ms -- url:${ctx.url}\n`);
  };
};

然后在 config.default.ts 中配置

   config.middleware = [ 'logger' ];

中间件和 Koa 的中间件写法是一模一样的,所以任何 Koa 的中间件都可以直接被框架使用。

向中间键传递参数

首先需要修改中间键的名称,因为上面写的 logger 与 eggjs 自带的中间键同名会发生冲突

修改 logger.ts 为 myLogger.ts.

然后修改 config.default.ts

  const bizConfig = {
    ...
    //  表示 myLogger 中间键需要传递的参数
    myLogger: {
      allowedMethod: [ 'POST' ],
    },
  };

在 中间键中接受参数

// options 就是中间键接受的参数对象
export default (options: any) => {
  return async (ctx: Context, next: () => Promise<any>) => {
    const startTime = Date.now();
    await next();
    if (options.allowedMethod.includes(ctx.method)) {
      appendFileSync('./log.txt', `time: ${Date.now() - startTime} ms -- url:${ctx.url}, method: ${ctx.method}\n`);
    }
  };
};

middleware 在特定的路由上使用也是可以的, 中间键会挂载到 app 对象上,因此我们可以在很多地方都可以使用中间键

import { Service } from 'egg';
export default class DogService extends Service {
 async show<T>() {
   this.app.middleware.myLogger
   const res = await this.ctx.curl<T>('https://dog.ceo/api/breeds/image/random', {
     dataType: 'json',
   });
   return res.data;
 }
}

0人推荐
随时随地看视频
慕课网APP