深入浅析node中的Nest.js框架

本篇文章带大家认识一下node中的Nest.js框架,聊聊为什么选择 Nest,创建和运行项目、不同方式接收请求的方法,希望对大家有所帮助!

最近在考虑和小伙伴做一个todolist平台给自己用,很久之前学习过 express ,想着与时俱进一下,看看近期热度较高的几个框架是怎样的。在几个对比下选择了 nest 在初步使用后记录一下,方便日后查阅。

贴出中文文档以便大家进一步学习 Nest

Nest.js框架简介

  • Nest 是一个用于构建高效,可扩展的 Node.js 服务器端应用程序的框架。它使用渐进式 JavaScript,内置并完全支持 TypeScript(但仍然允许开发人员使用纯 JavaScript 编写代码)并结合了 OOP(面向对象编程),FP(函数式编程)和 FRP(函数式响应编程)的元素。
  • Nest 框架底层 HTTP 平台默认是基于 Express 实现的,所以无需担心第三方库的缺失。 Nest 旨在成为一个与平台无关的框架。 通过平台,可以创建可重用的逻辑部件,开发人员可以利用这些部件来跨越多种不同类型的应用程序。 nest 目前有两个支持开箱即用的 HTTP 平台:express 和 fastify 可以在项目中直接引入。

为什么选择 Nest

  • 目前市面上有很多 node 框架可供大家选择。
  • Express.js 是 Node.JS 诞生之初,是一款基于Node.js以及Chrome V8引擎,快速、极简的JS服务端开发框架。
  • Koa.js是一款微型Web框架,写一个hello world很简单,但web应用离不开session,视图模板,路由,文件上传,日志管理。这些 Koa 都不提供,需要自行去官方的 Middleware 寻找。然而,100个人可能找出100种搭配。
  • Egg.js是基于Koa.js,解决了上述问题,将社区最佳实践整合进了Koa.js,另取名叫Egg.js,并且将多进程启动,开发时的热更新等问题一并解决了。这对开发者很友好,开箱即用,开箱即是最(较)佳配置。Egg.js发展期间,ECMAScript又推出了 async await,相比yield的语法async写起来更直。后面Koa.js也同步进行了跟进。
  • Midway 是阿里团队,基于渐进式理念研发的 Node.js 框架,结合了 OOP和函数式两种编程范式。以 egg 是作为底层框架,加上了良好的TypeScript的定义支持等众多新特性,推出了Midway,有兴趣的小伙伴可以去官方文档学习一下
  • Nest.js 基于Express.js的全功能框架 Nest.js,他是在Express.js上封装的,充分利用了TypeScript的特性;Nest.js的优点是社区活跃,涨势喜人,截止目前在 GitHub 拥有 43.7k Star 是近期比较热门的企业级框架。
  • 基于支持底层支持ts与企业级和社区活跃度等综合考虑,这里我选择用nest来进行学习。各位同学可以按需选择。

创建项目

  • 确保电脑安装了 Node.js (>= 10.13.0)

  • 这里我使用的 node 版本为 v14.16.1 包用的是 yarn 管理的 版本为 1.22.17

创建项目

  • $  npm i -g @nestjs/cli
    $  nest new project-name
  • 创建好项目后看一下项目目录,以下是核心文件的简单描述:

  • app.controller.ts带有单个路由的基本控制器示例
    app.controller.spec.ts对于基本控制器的单元测试样例
    app.module.ts应用程序的根模块。
    app.service.ts带有单个方法的基本服务
    main.ts应用程序入口文件。用来创建 Nest 应用实例。
    /* main.ts */
    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule); // 使用核心类 NestFactory 返回一个 接口对象
      await app.listen(3000);  // 这里是默认设置的端口号
    }
    bootstrap();

运行项目

  • $ npm run start:watch // 启动项目并监听代码变动 这里可以在package.json 中进行配置指令

1.png

  •   我们可以看到服务已经启动,输入本机地址并带上端口号3000,发送一次 get 请求 则会返回 `Hello World`。 
      
      这里是因为在 app.controll.ts 文件中 @Get()HTTP请求装饰器告诉Nest为HTTP请求的特定端点创建处理程序。

路由

  • 在开始写代码之前我们先简单看一下nest中的基础路由配置是怎样的,就目前而言我的理解为nest的路由是由 全局路由 路由前缀(局部路由) 方法装饰器 组成路由映射提供给前端使用。

  •  /* main.ts */
     main文件中我们可以在项目监听前配置一个全局的api前缀
    async function bootstrap() {
    const app = await NestFactory.create(AppModule);
        //设置全局前缀
        app.setGlobalPrefix('api');
        await app.listen(3000);
      }
    /* app.controller.ts */
    @Controller('user') // 控制器设置路由前缀 我理解为局部路由
      export class AppController {
        constructor(private readonly appService: AppService) {}
        @Get('find') // 方法装饰器设置路由路径 这里我理解为设置api子路由
        getHello(): string {
          return this.appService.getHello();
            }
        }
  • 以上方法在api中映射成完整的路由为GET api/user/find

  • 其中 @Get()HTTP请求装饰器告诉Nest为HTTP请求的特定端点创建处理程序。

2.png

  • 可以看到上面的 get 接收请求及路由以可以使用,下面我们看一下 nest 中如何接收 post 等其他请求方式

不同方式接收请求

  • 这里用到的 Nest 提供的请求装饰器知识点Request 对象代表 HTTP 请求,并具有查询字符串,请求参数参数,HTTP 标头(HTTP header) 和 正文(HTTP body)的属性(在这里阅读更多)。在多数情况下,不必手动获取它们。 我们可以使用专用的装饰器,比如开箱即用的 @Body()@Query() 。 下面是 Nest 提供的装饰器及其代表的底层平台特定对象的对照列表。

    3.png

  • 下面我们看一下 nest 中如何接收 get post put delete 发起的请求,用几个可用的装饰器来创建基本控制器。 该控制器暴露了几个访问和操作内部数据的方法。

Get

  • 我们先创建一个 user 服务/控制器/moudle

    / * user.service.ts  */ 先创建一个 user service服务文件
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 这里
       export class UserService {
         findUser(sid: string): string {
           console.log(sid);
           if (sid === '123456') {
             return 'kid is here';
           }
           return 'No one here';
         }
      }
  • 该服务将负责数据存储和检索,其由 UserController 使用,我们用 @Injectable() 来装饰这个类

    / * user.controller.ts  */ 创建一个 user 控制器文件
    import { Controller, Get, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserController {
       constructor(private readonly userService: UserService) {}
       @Get('findOne') //这里暴露出的路由为 user/find
       findUser(@Query() query: any) {
         return this.userService.findUser(query.sid);
       }
  • 控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。

  • 为了创建一个基本的控制器,我们使用类和装饰器。装饰器将类与所需的元数据相关联,并使 Nest 能够创建路由映射(将请求绑定到相应的控制器)。

    / * user.module.ts  */ 创建一个 user mod
     import { Module } from '@nestjs/common';
     import { UserController } from './user.controller';
     import { UserService } from './user.service';
     @Module({
         controllers: [UserController],
         providers: [UserService],
       })
       export class UserModule {}
    
    /*  app.module.ts  */ 最后在app.module中引入我们自己写的module
    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { UserModule } from './user/user.module';
    
    @Module({
         imports: [UserModule],
         controllers: [AppController],
         providers: [AppService],
       })
       export class AppModule {}
  • 控制器已经准备就绪,可以使用,但是 Nest 依然不知道 UserController 是否存在,所以它不会创建这个类的一个实例。

  • 控制器总是属于模块,这就是为什么我们在 @Module() 装饰器中包含 controllers 数组的原因。 由于除了根模块 AppModule之外,我们还没有定义其他模块,所以我们将使用它来介绍 UserController

    使用 postman 看下效果

    4.png

    • 可以看到发送get请求 请求成攻。
    • 接下来我们依次使用 post put delete 发送请求,看nest是如何接受并处理的

Post

  • user.service 文件

    / * user.service.ts  */ 先创建一个 user service服务文件
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 这里
      setUser(sid: string, body: any): any {
           if (sid === '123456') {
             return {
               msg: '设置成功',
               body,
             };
         }
      }
  • user.controller 文件

    / * user.controller.ts  */ 创建一个 user 控制器文件
    import { Controller, Get, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserService {
        @Post('set')
        setUser(@Body() body: any, @Query() query: any) {
          return this.userService.setUser(query.sid, body);
        } 
    }

使用 postman 看下效果

5.png

  • 可以看到发送 post 请求 请求成攻。

Put

  • user.service 文件

    / * user.service.ts  */ 先创建一个 user service服务文件
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 这里
      updateUser(sid: string, body: any): any {
           if (sid === '123456') {
             return {
               msg: '设置成功',
               body,
             };
         }
      }
  • user.controller 文件

  • 这里用到了 Param 装饰器 @Param() 用于修饰一个方法的参数(上面示例中的 params),并在该方法内将路由参数作为被修饰的方法参数的属性。如上面的代码所示,我们可以通过引用 params.id来访问(路由路径中的) id 参数。 您还可以将特定的参数标记传递给装饰器,然后在方法主体中按参数名称直接引用路由参数。

    / * user.controller.ts  */ 创建一个 user 控制器文件
    import { Body, Controller, Get, Param, Post, Put, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserService {
       @Put(':sid')
       updateUser(@Param('sid') sid: string, @Body() body: any) {
         return this.userService.updateUser(sid, body);
       }
    }

使用 postman 看下效果

6.png

  • 可以看到发送 put 请求 请求成攻。

Delete

  • user.service 文件

    / * user.service.ts  */ 先创建一个 user service服务文件
    import { Injectable } from '@nestjs/common';
       @Injectable() // 
       // 这里
     deleteUser(sid: string): any {
           if (sid === '123456') {
             return {
               msg: '删除成功',
             };
         }
      }
  • user.controller 文件

    / * user.controller.ts  */ 创建一个 user 控制器文件
    import { Body, Controller, Get, Param, Post, Put, Query } from '@nestjs/common';
    import { UserService } from './user.service';
    
    @Controller('user')
    export class UserService {
       @Delete(':sid')
       deleteUser(@Param('sid') sid: string) {
         return this.userService.deleteUser(sid);
       }
    }

使用 postman 看下效果

7.png

  • 可以看到发送 delete 请求 请求成攻。

总结

  • 至此我们用 Nest 的装饰器模拟了基础的接口请求增删改查,认识到 Nest 中的三种基本应用程序构建块Module Controller Service
  • 服务和控制的划分明确,带来更好的代码体验。TypeScrip 的个人使用还有待提高,以后还要继续学习hhh

更多node相关知识,请访问:nodejs 教程

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)