egg学习笔记之基础语法

1,022 阅读4分钟

1.项目结构

egg-project
├── package.json
├── app.js (可选)
├── agent.js (可选)
├── app
|   ├── router.js
│   ├── controller
│   |   └── home.js
│   ├── service (可选)
│   |   └── user.js
│   ├── middleware (可选)
│   |   └── response_time.js
│   ├── schedule (可选)
│   |   └── my_task.js
│   ├── public (可选)
│   |   └── reset.css
│   ├── view (可选)
│   |   └── home.tpl
│   └── extend (可选)
│       ├── helper.js (可选)
│       ├── request.js (可选)
│       ├── response.js (可选)
│       ├── context.js (可选)
│       ├── application.js (可选)
│       └── agent.js (可选)
├── config
|   ├── plugin.js
|   ├── config.default.js
│   ├── config.prod.js
|   ├── config.test.js (可选)
|   ├── config.local.js (可选)
|   └── config.unittest.js (可选)
└── test
    ├── middleware
    |   └── response_time.test.js
    └── controller
        └── home.test.js

2.内置对象

  • context,response,request,application(koa继承来的)
  • Controller, Service, Helper, Config, Logger (扩展的)

application对象

  • application是全局对象,继承自koa.application,一个应用中只可实例化一个对象。在上面可以挂载一些全局的方法和对象。
  • application上有一些事件,开发者可以监听这一事件做一些操作。
  1. server:该事件一个 worker 进程只会触发一次,在 HTTP 服务完成启动后,会将 HTTP server 通过这个事件暴露出来给开发者。
  2. error: 运行时有任何的异常被 onerror 插件捕获后,都会触发 error 事件,将错误对象和关联的上下文(如果有)暴露给开发者,可以进行自定义的日志记录上报等处理。
  3. request 和 response: 应用收到请求和响应请求时,分别会触发 request 和 response 事件,并将当前请求上下文暴露出来,开发者可以监听这两个事件来进行日志记录。
// app.js

module.exports = app => {
  app.once('server', server => {
    // websocket
  });
  app.on('error', (err, ctx) => {
    // report error
  });
  app.on('request', ctx => {
    // log receive request
  });
  app.on('response', ctx => {
    // ctx.starttime is set by framework
    const used = Date.now() - ctx.starttime;
    // log total cost
  });
};

  • 获取application

几乎在编写应用的任何一个地方都可以获取到。几乎所有被框架 Loader 加载的文件(Controller,Service,Schedule 等),都可以 export 一个函数,这个函数会被 Loader 调用,并使用 app 作为参数.

context

Context 是一个请求级别的对象,继承自 Koa.Context。在每一次收到用户请求时,框架会实例化一个 Context 对象,这个对象封装了这次用户请求的信息,并提供了许多便捷的方法来获取请求参数或者设置响应信息。

  1. 获取方式

最常见的 Context 实例获取方式是在 Middleware, Controller 以及 Service 中。

async function middleware(ctx, next) {
  // ctx is instance of Context
  console.log(ctx.query);
}

在有些非用户请求的场景下我们需要访问 service / model 等 Context 实例上的对象,我们可以通过 Application.createAnonymousContext() 方法创建一个匿名 Context 实例

// app.js
module.exports = app => {
  app.beforeStart(async () => {
    const ctx = app.createAnonymousContext();
    // preload before app start
    await ctx.service.posts.load();
  });
}

request和response

Request 是一个请求级别的对象,继承自 Koa.Request。封装了 Node.js 原生的 HTTP Request 对象,提供了一系列辅助方法获取 HTTP 请求常用参数。

Response 是一个请求级别的对象,继承自 Koa.Response。封装了 Node.js 原生的 HTTP Response 对象,提供了一系列辅助方法设置 HTTP 响应。

  1. 获取方式

可以在 Context 的实例上获取到当前请求的 Request(ctx.request) 和 Response(ctx.response) 实例。

// app/controller/user.js
class UserController extends Controller {
  async fetch() {
    const { app, ctx } = this;
    const id = ctx.request.query.id;
    ctx.response.body = app.cache.get(id);
  }
}

如上面例子中的 ctx.request.query.idctx.query.id 是等价的,ctx.response.body= 和 ctx.body= 是等价的。

需要注意的是,获取 POST 的 body 应该使用 ctx.request.body,而不是 ctx.body。

controller

框架提供了一个 Controller 基类,并推荐所有的 Controller 都继承于该基类实现。其有如下属性:

  1. ctx - 当前请求的 Context 实例。
  2. app - 应用的 Application 实例。
  3. config - 应用的配置。
  4. service - 应用所有的 service。
  5. logger - 为当前 controller 封装的 logger 对象。
  • controller有如下两种引入方式
// app/controller/user.js

// 从 egg 上获取(推荐)
const Controller = require('egg').Controller;
class UserController extends Controller {
  // implement
}
module.exports = UserController;

// 从 app 实例上获取
module.exports = app => {
  return class UserController extends app.Controller {
    // implement
  };
};

service

框架提供了一个 Service 基类,并推荐所有的 Service 都继承于该基类实现。

Service 基类的属性和 Controller 基类属性一致,访问方式也类似

helper

Helper 用来提供一些实用的 utility 函数。它的作用在于我们可以将一些常用的动作抽离在 helper.js 里面成为一个独立的函数

  1. 获取方法:可以在context中获得、模板中获得
// app/controller/user.js
class UserController extends Controller {
  async fetch() {
    const { app, ctx } = this;
    const id = ctx.query.id;
    const user = app.cache.get(id);
    ctx.body = ctx.helper.formatUser(user);
  }
}
// app/view/home.nj
{{ helper.shtml(value) }}

config对象

  1. 获取方法

我们可以通过 app.config 从 Application 实例上获取到 config 对象,也可以在 Controller, Service, Helper 的实例上通过 this.config 获取到 config 对象。

logger对象

框架内置了功能强大的日志功能,可以非常方便的打印各种级别的日志到对应的日志文件中,每一个 logger 对象都提供了 5 个级别的方法:

  • logger.debug()
  • logger.info()
  • logger.warn()
  • logger.error()