Node框架 【Egg-企业级框架】之 【内置对象】

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Node框架 【Egg-企业级框架】之 【内置对象】

🌟前言

哈喽小伙伴们,新的专栏 Node 已开启;这个专栏里边会收录一些Node的基础知识和项目实战;今天我们继续带大家了解Node的框架 Egg ;让我们一起来看看吧🤘

🌟 框架内置对象

框架中内置的一些基础对象:

类型 描述
Koa 继承对象 Application, Context, Request, Response
框架扩展对象 Controller, Service, Helper, Config, Logger


🌟Koa 继承对象

🌟Koa Application

Application 是全局应用对象,在一个应用中,只会实例化一个,它继承自 Koa.Application,在它上面我们可以挂载一些全局的方法和对象。我们可以轻松的在插件或者应用中扩展 Application对象。

🌟事件

在框架运行时,会在 Application 实例上触发一些事件,应用开发者或者插件开发者可以监听这些事件做一些操作。作为应用开发者,我们一般会在启动自定义脚本中进行监听。

事件

描述

server

该事件一个 worker 进程只会触发一次,在 HTTP 服务完成启动后,会将 HTTP server 通过这个事件暴露出来给开发者。

error

运行时有任何的异常被 onerror 插件捕获后,都会触发 error 事件,将错误对象和关联的上下文(如果有)暴露给开发者,可以进行自定义的日志记录上报等处理。

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 作为参数:

启动自定义脚本

// app.js
module.exports = app => {
  // app
  app.cache = new Cache();
};

    Controller、Service文件 在继承于 Controller, Service 基类的实例中,可以通过 this.app 访问到 Application 对象。

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

    和 Koa 一样,在 Context 对象上,可以通过 ctx.app 访问到 Application 对象。以上面的 Controller 文件举例:

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

    🌟全局应用对象的属性

    属性

    类型

    描述

    app.baseDir

    String

    应用程序的根目录

    app.config

    Object

    应用程序的配置

    app.env

    String

    app.env 等同于 app.config.env

    app.plugins

    Object

    应用程序的配置

    app.middleware

    Object

    中间件列表

    app.controller

    Object

    控制器列表

    app.router

    Object

    获取路由对象

    app.locals

    Object

    View的全局变量

    🌟Context

    Context 是一个请求级别的对象,继承自 Koa.Context。在每一次收到用户请求时,框架会实例化一个 Context 对象,这个对象封装了这次用户请求的信息,并提供了许多便捷的方法来获取请求参数或者设置响应信息。框架会将所有的 Service 挂载到 Context 实例上,一些插件也会将一些其他的方法和对象挂载到它上面(egg-sequelize 会将所有的 model 挂载在 Context 上)。

    🌟获取Context的方式

    最常见的 Context 实例获取方式是在 Middleware, Controller 以及 Service 中。Controller 中的获取方式在上面的例子中已经展示过了,在 Service 中获取和 Controller 中获取的方式一样,在 Middleware 中获取 Context 实例则和 Koa 框架在中间件中获取 Context 对象的方式一致。


    Controller 中的获取Context:

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

    在 Service 中获取和 Controller 中获取的方式一样:

    // app/service/news.js
    const Service = require('egg').Service;
    class NewsService extends Service {
      async list(page = 1) {
          // this.ctx 获取Context
      }
    }
    

    框架的 Middleware 同时支持 Koa v1 和 Koa v2 两种不同的中间件写法,根据不同的写法,获取 Context 实例的方式也稍有不同:

    // Koa v1
    function* middleware(next) {
      // this is instance of Context
      console.log(this.query);
      yield next;
    }
    // Koa v2
    async function middleware(ctx, next) {
      // ctx is instance of Context
      console.log(ctx.query);
    }
    

    在定时任务中的每一个 task 都接受一个 Context 实例作为参数,以便我们更方便的执行一些定时的业务逻辑:

    // app/schedule/refresh.js
    exports.task = async ctx => {
      await ctx.service.posts.refresh();
    };

    🌟Request & Response

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


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


    🌟获取方式

    可以在 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);
      }
    }
    

    Koa 会在 Context 上代理一部分 Request 和 Response 上的方法和属性,参见 Koa.Context。

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

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

    🌟框架扩展对象

    🌟Controller

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


    ctx - 当前请求的 Context 实例。

    app - 应用的 Application 实例。

    config - 应用的配置。

    service - 应用所有的 service。

    logger - 为当前 controller 封装的 logger 对象。

    在 Controller 文件中,可以通过两种方式来引用 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 基类属性一致,访问方式也类似:

    // app/service/user.js
    // 从 egg 上获取(推荐)
    const Service = require('egg').Service;
    class UserService extends Service {
      // implement
    }
    module.exports = UserService;
    // 从 app 实例上获取
    module.exports = app => {
      return class UserService extends app.Service {
        // implement
      };
    };
    

    🌟Helper

    Helper 用来提供一些实用的 utility 函数。它的作用在于我们可以将一些常用的动作抽离在 helper.js 里面成为一个独立的函数,这样可以用 JavaScript 来写复杂的逻辑,避免逻辑分散各处,同时可以更好的编写测试用例。


    Helper 自身是一个类,有和 Controller 基类一样的属性,它也会在每次请求时进行实例化,因此 Helper 上的所有函数也能获取到当前请求相关的上下文信息。

    🌟获取方式

    可以在 Context 的实例上获取到当前请求的 Helper(ctx.helper) 实例。

    // 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);
      }
    }
    

    除此之外,Helper 的实例还可以在模板中获取到,例如可以在模板中获取到 security 插件提供的 shtml 方法。

    // app/view/home.nj
    {{ helper.shtml(value) }}
    

    🌟自定义 helper 方法

    应用开发中,我们可能经常要自定义一些 helper 方法,例如上面例子中的 formatUser,我们可以通过框架扩展的形式来自定义 helper 方法。

    // app/extend/helper.js
    module.exports = {
      formatUser(user) {
        return only(user, ['name', 'phone']);
      },
    };
    

    🌟Config

    我们推荐应用开发遵循配置和代码分离的原则,将一些需要硬编码的业务配置都放到配置文件中,同时配置文件支持各个不同的运行环境使用不同的配置,使用起来也非常方便,所有框架、插件和应用级别的配置都可以通过 Config 对象获取到


    🌟获取方式

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


    🌟Logger

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


    logger.debug()

    logger.info()

    logger.warn()

    logger.error()


    相关实践学习
    日志服务之使用Nginx模式采集日志
    本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
    目录
    相关文章
    |
    19天前
    |
    存储 缓存 JavaScript
    构建高效后端服务:Node.js与Express框架的实战应用
    【8月更文挑战第2天】在数字化时代的浪潮中,后端服务的构建成为了软件开发的核心。本文将深入探讨如何利用Node.js和Express框架搭建一个高效、可扩展的后端服务。我们将通过实际代码示例,展示从零开始创建一个RESTful API的全过程,包括路由设置、中间件使用以及数据库连接等关键步骤。此外,文章还将触及性能优化和安全性考量,旨在为读者提供一套完整的后端开发解决方案。让我们一同走进Node.js和Express的世界,探索它们如何助力现代Web应用的开发。
    |
    16天前
    |
    JavaScript 前端开发 测试技术
    Node.js新手框架推荐
    【8月更文挑战第4天】Node.js新手框架推荐
    26 3
    |
    16天前
    |
    弹性计算 JavaScript 中间件
    构建高效后端服务:使用Node.js和Express框架
    【8月更文挑战第4天】本文将通过一个实际案例,详细介绍如何使用Node.js和Express框架快速构建一个高效、可扩展的后端服务。我们将从项目初始化开始,逐步实现RESTful API接口,并介绍如何利用中间件优化请求处理流程。最后,我们将展示如何部署应用到云服务器上,确保其高可用性和可扩展性。
    |
    5天前
    |
    JavaScript 前端开发 Ubuntu
    如何在 VPS 上安装 Express(Node.js 框架)并设置 Socket.io
    如何在 VPS 上安装 Express(Node.js 框架)并设置 Socket.io
    12 0
    |
    1月前
    |
    开发框架 监控 JavaScript
    使用Node.js 框架( Express.js)来创建一个简单的 API 端点
    【7月更文挑战第5天】使用Node.js 框架( Express.js)来创建一个简单的 API 端点
    23 3
    |
    20天前
    |
    JavaScript 前端开发 中间件
    构建高效后端服务:Node.js与Express框架的深度探索
    【7月更文挑战第31天】在快速迭代的技术浪潮中,Node.js和Express框架已成为构建灵活、高效后端服务的利器。本文将深入探讨如何利用这一组合打造高性能后端系统,同时分享实际开发中的经验和技巧。
    19 0
    |
    1月前
    |
    开发框架 监控 JavaScript
    企业级node.js开发框架 【egg.js】 实用教程
    企业级node.js开发框架 【egg.js】 实用教程
    23 0
    |
    2月前
    |
    JavaScript 前端开发 中间件
    Express框架搭建项目 node.js
    【6月更文挑战第3天】这篇文章是关于使用Express框架构建Node.js Web应用的教程。Express是一个轻量级、功能丰富的框架,特点包括简洁灵活的核心、强大的中间件支持、灵活的路由系统和模板引擎兼容性。文章介绍了如何安装Express,并通过一个简单的示例展示了如何创建一个基本的Web服务器。最后,鼓励读者继续学习和实践,以充分利用Express和Node.js的能力。
    63 1
    |
    2月前
    |
    JSON JavaScript 中间件
    Node.js Express 框架
    Node.js Express 框架
    25 0
    |
    3月前
    |
    Web App开发 JavaScript Cloud Native
    构建高效可扩展的RESTful API:Node.js与Express框架实践指南构建未来:云原生架构在企业数字化转型中的关键作用
    【5月更文挑战第29天】 在数字化时代的驱动下,后端服务架构的稳定性与效率成为企业竞争力的关键。本文深入探讨了如何利用Node.js结合Express框架构建一个高效且可扩展的RESTful API。我们将从设计理念、核心模块、中间件应用以及性能优化等方面进行系统性阐述。通过实例引导读者理解RESTful接口设计的最佳实践,并展示如何应对大规模并发请求的挑战,确保系统的高可用性与安全性。