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日志并进行多维度分析。
    目录
    相关文章
    |
    28天前
    |
    存储 缓存 JavaScript
    node 框架
    Node 框架以其独特的优势和广泛的应用场景,成为了现代 Web 开发中不可或缺的一部分。掌握 Node 框架的开发技能,对于开发者来说具有重要的意义。
    101 59
    |
    28天前
    |
    安全 前端开发 JavaScript
    Node框架的优缺点
    Node 框架的优点使其在现代 Web 开发中具有重要地位,但同时也需要开发者在使用过程中注意其缺点,合理选择和应用,以充分发挥其优势,避免潜在问题的出现。随着技术的不断发展和完善,Node 框架也在不断改进和优化,以更好地适应各种应用需求。
    60 28
    |
    1月前
    |
    Web App开发 JavaScript 前端开发
    深入浅出Node.js后端框架
    【10月更文挑战第34天】在数字化时代,后端开发如同一座桥梁,连接着用户界面与数据处理的两端。本文将通过Node.js这一轻量级、高效的平台,带领读者领略后端框架的魅力。我们将从基础概念出发,逐步深入到实战应用,最后探讨如何通过代码示例来巩固学习成果,使读者能够在理论与实践之间架起自己的桥梁。
    |
    27天前
    |
    Web App开发 缓存 监控
    如何解决Node框架中内存管理的挑战?
    解决 Node 框架中内存管理的挑战需要综合运用多种方法,并且需要在开发过程中保持谨慎和细心,不断优化和改进代码。同时,定期进行内存管理的检查和维护也是非常重要的。
    109 63
    |
    27天前
    |
    缓存 负载均衡 JavaScript
    构建高效后端服务:Node.js与Express框架实践
    在数字化时代的浪潮中,后端服务的重要性不言而喻。本文将通过深入浅出的方式介绍如何利用Node.js及其强大的Express框架来搭建一个高效的后端服务。我们将从零开始,逐步深入,不仅涉及基础的代码编写,更会探讨如何优化性能和处理高并发场景。无论你是后端新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启示。
    |
    28天前
    |
    存储 JavaScript 搜索推荐
    Node框架的安装和配置方法
    安装 Node 框架是进行 Node 开发的第一步,通过正确的安装和配置,可以为后续的开发工作提供良好的基础。在安装过程中,需要仔细阅读相关文档和提示,遇到问题及时解决,以确保安装顺利完成。
    81 2
    |
    1月前
    |
    JavaScript 中间件 API
    Node.js进阶:Koa框架下的RESTful API设计与实现
    【10月更文挑战第28天】本文介绍了如何在Koa框架下设计与实现RESTful API。首先概述了Koa框架的特点,接着讲解了RESTful API的设计原则,包括无状态和统一接口。最后,通过一个简单的博客系统示例,详细展示了如何使用Koa和koa-router实现常见的CRUD操作,包括获取、创建、更新和删除文章。
    48 4
    |
    2月前
    |
    Web App开发 JavaScript 中间件
    构建高效后端服务:Node.js与Express框架的完美结合
    【10月更文挑战第21天】本文将引导你走进Node.js和Express框架的世界,探索它们如何共同打造一个高效、可扩展的后端服务。通过深入浅出的解释和实际代码示例,我们将一起理解这一组合的魅力所在,并学习如何利用它们来构建现代Web应用。
    64 1
    |
    1月前
    |
    Web App开发 JavaScript 前端开发
    构建高效后端服务:Node.js与Express框架的实践
    【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
    |
    1月前
    |
    Web App开发 JavaScript 中间件
    构建高效后端服务:Node.js与Express框架的融合之道
    【10月更文挑战第31天】在追求快速、灵活和高效的后端开发领域,Node.js与Express框架的结合如同咖啡遇见了奶油——完美融合。本文将带你探索这一组合如何让后端服务搭建变得既轻松又充满乐趣,同时确保你的应用能够以光速运行。
    34 0
    下一篇
    DataWorks