做购物网站的初衷/如何推广自己的微信公众号

做购物网站的初衷,如何推广自己的微信公众号,wordpress用户管理,北京旅游网站建设Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用JavaScript 的渐进增强的能力,使用并完全支持 TypeScript (仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对…

Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用JavaScript 的渐进增强的能力,使用并完全支持 TypeScript (仍然允许开发者使用纯 JavaScript 进行开发),并结合了 OOP (面向对象编程)、FP (函数式编程)和 FRP (函数响应式编程)。

在底层,Nest 构建在强大的 HTTP 服务器框架上,例如 Express (默认),并且还可以通过配置从而使用 Fastify !

Nest 在这些常见的 Node.js 框架 (Express/Fastify) 之上提高了一个抽象级别,但仍然向开发者直接暴露了底层框架的 API。这使得开发者可以自由地使用适用于底层平台的无数的第三方模块。

NestJS 是一个基于 TypeScript 的服务器端应用程序框架。 它提供了一组丰富的工具和模块来帮助开发人员构建高效、可扩展的服务器端应用程序。这些元素可以通过依赖注入系统自动注册,并可以在整个应用程序中共享

总的来说,NestJS 是一个功能丰富、易于使用的服务器端应用程序框架,可帮助开发人员快速构建高效、可扩展的服务器端应用程序。

一、NestJS优势

NestJS 的一些优势包括:

  • 构建在现代 JavaScript 栈之上,因此使用了最新的 JavaScript 技术。
  • 基于 Angular 的架构和语法,提供了强大的模块化系统和依赖注入功能。
  • 基于 TypeScript,提供了强类型和静态类型检查。
  • 提供了丰富的工具和模块,可用于构建各种类型的服务器端应用程序,包括 RESTful API、GraphQL API、WebSocket 服务器等。
  • 提供了一组可扩展的构建块,可用于快速构建应用程序。
  • 提供了与主流数据库和身份验证系统的集成。

二、IOC(控制反转 )和依赖注入DI概念

这两个概念不要搞混了,IOC其实是面向对象编程中的一种设计模式,而DI则是为了实现IOC的一种技术。

下面简单认识一下为什么需要IOC,IOC有什么好处,简单来说就是减少了固定性,通过外部传参进行控制内部本身固定的一些变量,如下例子:

在我们的代码中,经常会出现一个类依赖于另外一个类的情况,比如这样:

class Dog {}class Person {private _petconstructor () {this._pet = new Dog()}
}const xiaoming = new Person()

当我们遇到类与类之间存在依赖关系时,一般会直接在类的内部创建依赖对象,这样就会导致各个类之间形成耦合,并且这种关系会随着依赖关系越来越复杂从而耦合度也会越来越高,最终造成代码的难以维护。

在上述例子中:

  • Person类固定依赖于Dog类,如果后续Person想要依赖于其他宠物类,是无法轻易修改的。
  • 并且如果Dog类有所变化,比如其属性颜色染成了黑色,Person类也会直接受到影响。

IOC的思想就是将类的依赖动态注入,以解决上述两个问题:

class Dog {}class Person {private _petconstructor (pet) {this._pet = pet}
}const xiaohei = new Dog()
const xiaoming = new Person(xiaohei) // 将实例化的 dog 传入 person 类

这样,我们就实现了类的控制反转,同时,我们需要有一个容器来维护各个对象实例,当用户需要使用实例时,容器会自动将对象实例化给用户,这部分通常由框架处理。

这种动态注入的思想叫做依赖注入(DI, Dependency Injection),它是 IoC 的一种应用形式,把对象或依赖的实例化交给IOC容器去处理,在NestJS中这个容器就是NestJS的运行时系统。当需要一个对象实例的时候,我们不需要自己手动new xxxClass(),只需要在合适的地方对类进行注册,在需要用到的地方直接注入,容器将为我们完成new的动作。

三、NestJs中使用方式

Nest中使用依赖注入一般有以下三步:

1、声明定义

使用@Injectable装饰器来声明一个类,它表示该类可以由NestIOC容器管理

通常命名方式为XXX.service.ts

// app.service.ts
import { Injectable } from '@nestjs/common';@Injectable()
export class AppService {getHello(): string {return 'Hello jiusi';}
}

2、声明在什么地方使用

这是依赖注入的地方,一般是在类的构造函数constructor中注入,只有完成注入后才可以使用

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) {}@Get('/hello')get(): string {return this.appService.getHello();}
}

官方把appService称为tokenNestJS会根据这个token在容器中找到第1步中声明的类(这个对应关系将在第三步中进行关联注册),从而提供对应的实例,这里的实例全局唯一,只有1个!在第一次需要该实例的时候,Nestnew一个出来,而后会缓存起来,后序如果其它地方也注入了这个依赖,那Nest会从缓存中拿到之前new出来的实例供大家使用。

3、建立注入依赖与容器中类的联系

依赖注入后还需要在Module中进行关联

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';@Module({controllers: [AppController],providers: [AppService],
})
export class AppModule {}

Nest会根据所有注入的依赖关系生成一个依赖关系图,就有点类似我们使用import引入各个模块时也会生成一个复杂的依赖关系图。这里AppController中依赖了AppService,如果AppService中还依赖其它东西也会一并放到Nest构建的依赖关系图中,Nest会从下到上按照依赖顺序构建出一整张依赖关系图保证所有的依赖关系正常运作。

四、AOP(Aspect Oriented Programming)

中文为面向切面编程。当一个请求打过来时,一般会经过 Controller(控制器)、Service(服务)、Repository(数据库访问) 的链路。当我们不使用AOP时,需要添加一些通用逻辑时(如日志记录、权限守卫、异常处理等等),就需要在每段请求逻辑中编写相关代码。

AOP就是在所有请求外面包裹一层切面,所有请求都会经过这个切面,然后我们就可以把上述的通用逻辑放在这个结构里,如下图:

在这里插入图片描述

在nestJS中实现AOP的方式有很多,比如(excepion filter过滤器、pipes管道、guards守卫、interceptors拦截器)。

五、NestJS请求流程图

  • Controllers -> 处理请求
  • Service -> 数据访问与核心逻辑
  • Modules -> 组合所有的逻辑代码
  • Pipes -> 管道–核验请求的数据
  • Filters -> 过滤器–处理请求时的错误
  • Guards -> 守卫–鉴权与认证
  • Interceptors -> 拦截器-给请求与响应加入额外的逻辑
  • Repositories -> 处理在数据库中数据

六、构建NestJs实际项目

在这里插入图片描述

1、项目创建

首先确定你已经安装了Node.js, Node.js 安装会附带npx和一个npm 包运行程序。要创建新的Nest.js 应用程序,请在终端上运行以下命令:

npm i -g @nestjs/cli  // 全局安装Nest
nest new project-name  // 创建项目

执行完创建项目, 会初始化下面这些文件, 并且询问你要是有什么方式来管理依赖包。

如果你有安装yarn,可以选择yarn,能更快一些。

注意: Nest.js 要求 Node.js(>= 10.13.0,v13 除外), 如果你的Node.js 版本不满足要求,可以通过nvm包管理工具安装符合要求的Node.js版本

2、项目结构

src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── main.ts
app.controller.ts单个路由的基本控制器(Controller)
app.controller.spec.ts针对控制器的单元测试
app.module.ts应用程序的根模块(Module)
app.service.ts具有单一方法的基本服务(Service)
main.ts应用程序的入口文件,它使用核心函数 NestFactory 来创建 Nest 应用程序的实例。

3、第一个接口

前面我们已经启动了服务, 那我们怎么查看呢, 首先就是找到入口文件main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';async function bootstrap() {const app = await NestFactory.create(AppModule);await app.listen(3000);
}
bootstrap();

内容比较简单, 使用Nest.js的工厂函数NestFactory来创建了一个AppModule实例,启动了 HTTP 侦听器,以侦听main.ts 中所定义的端口。

监听的端口号可以自定义, 如果3000端口被其他项目使用,可以更改为其他的端口号

前边看到main.ts中也没有别的文件引入, 只有AppModule, 打开src/app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';@Module({imports: [],controllers: [AppController],providers: [AppService],
})
export class AppModule {}

AppModule是应用程序的根模块,根模块提供了用来启动应用的引导机制,可以包含很多功能模块。

.mudule文件需要使用一个@Module() 装饰器的类,装饰器可以理解成一个封装好的函数,其实是一个语法糖(对装饰器不了解的,可以看走近MidwayJS:初识TS装饰器与IoC机制)。@Module() 装饰器接收四个属性:providerscontrollersimportsexports

  • providers:Nest.js注入器实例化的提供者(服务提供者),处理具体的业务逻辑,各个模块之间可以共享(注入器的概念后面依赖注入部分会讲解);
  • controllers:处理http请求,包括路由控制,向客户端返回响应,将具体业务逻辑委托给providers处理;
  • imports:导入模块的列表,如果需要使用其他模块的服务,需要通过这里导入;
  • exports:导出服务的列表,供其他模块导入使用。如果希望当前模块下的服务可以被其他模块共享,需要在这里配置导出;

app.module.ts中,看到它引入了app.controller.tsapp.service.ts,分别看一下这两个文件:

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) {}@Get()getHello(): string {return this.appService.getHello();}
}

使用@Controller装饰器来定义控制器, @Get是请求方法的装饰器,对getHello方法进行修饰, 表示这个方法会被GET请求调用。

// app.service.ts
import { Injectable } from '@nestjs/common';@Injectable()
export class AppService { getHello(): string {return 'Hello World!';}
}

从上面,我们可以看出使用@Injectable修饰后的 AppService, 在AppModule中注册之后,在app.controller.ts中使用,我们就不需要使用new AppService()去实例化,直接引入过来就可以用。

至此,对于http://localhost:9080/接口返回的Hello World逻辑就算理清楚了, 在这基础上我们再详细的学习一下Nest.js中的路由使用。

4、路由装饰器

Nest.js中没有单独配置路由的地方,而是使用装饰器。Nest.js中定义了若干的装饰器用于处理路由。

@Controller

如每一个要成为控制器的类,都需要借助@Controller装饰器的装饰,该装饰器可以传入一个路径参数,作为访问这个控制器的主路径:

app.controller.ts文件进行修改

// 主路径为 app
@Controller("app")
export class AppController {constructor(private readonly appService: AppService) {}@Get()getHello(): string {return this.appService.getHello();}
}

然后重新启一下服务。

5、HTTP方法处理装饰器

@Get@Post@Put等众多用于HTTP方法处理装饰器,经过它们装饰的方法,可以对相应的HTTP请求进行响应。同时它们可以接受一个字符串或一个字符串数组作为参数,这里的字符串可以是固定的路径,也可以是通配符。

继续修改app.controller.ts,看下面的例子:

// 主路径为 app
@Controller("app")
export class AppController {constructor(private readonly appService: AppService) {}// 1. 固定路径:// 可以匹配到 get请求,http://localhost:9080/app/list@Get("list")getHello(): string {...}// 可以匹配到 post请求,http://localhost:9080/app/list@Post("list")create():string{...}// 2.通配符路径(?+* 三种通配符 )// 可以匹配到 get请求, http://localhost:9080/app/user_xxx@Get("user_*")getUser(){return "getUser"}// 3.带参数路径// 可以匹配到put请求,http://localhost:9080/app/list/xxxx@Put("list/:id")update(){ return "update"}
}

由于修改了文件, 需要重启才能看到路由, 每次都重启简直就是噩梦,本来打算配置一个实时监听文件变化,发现Nest.js非常贴心的配置好了, 我们只要运行命令即可:

npm run start:dev

这样再修改什么内容, 保存后都会自动重启服务了。

6、全局路由前缀

除了上面这些装饰器可以设置路由外, 我们还可以设置全局路由前缀, 比如给所以路由都加上/api前缀。此时需要修改main.ts

async function bootstrap() {const app = await NestFactory.create(AppModule);app.setGlobalPrefix('api'); // 设置全局路由前缀await app.listen(3000);
}
bootstrap();

此时之前的路由,都要变更为:

http://localhost:3000/api/xxxx

到此我们认识了ControllerServiceModule、路由以及一些常用的装饰器, 那接下来就实战一下,我们以开发文章(Post)模块作为案例, 实现文章简单的CRUD,带大家熟悉一下这个过程。

七、创新新模块CURD

  • 创建服务类

nest g service posts

// src/posts/posts.service.ts
import { Injectable } from '@nestjs/common';@Injectable()
export class PostsService {}

创建app.service.ts文件,并且在app.module.ts文件下,@Module装饰器的providers中注入注入。

其实nest-cli提供的创建命令还有很多, 比如创建过滤器、拦截器和中间件等,由于这里暂时用不到,就不过多的介绍,后面章节用到了再介绍。

八、简单CURD创建

  • nest g resource user 一键搞定整个模块

    • 执行完毕后就自动生成了一个 user 文件夹,同时在app.module.ts也进行了自动导入
    • 来到`user.controller.ts`中我们会发现它已经帮你写好了这些请求的示例
      
import {Controller,Get,Post,Body,Patch,Param,Delete,
} from '@nestjs/common';
import { UserService } from './user.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';@Controller('user')
export class UserController {constructor(private readonly userService: UserService) {}@Post()create(@Body() createUserDto: CreateUserDto) {return this.userService.create(createUserDto);}@Get()findAll() {return this.userService.findAll();}@Get(':id')findOne(@Param('id') id: string) {return this.userService.findOne(+id);}@Patch(':id')update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {return this.userService.update(+id, updateUserDto);}@Delete(':id')remove(@Param('id') id: string) {return this.userService.remove(+id);}
}

我们可以看到有很多装饰器,像@Controller(‘user’)定义的是请求路径user,而@Get,@Post等这些就代表请求方式的装饰器,比如你用 POSt 请求调用http://localhost:3000/user就会进入@Post()下面的 create()方法(这里你需要一个模拟请求的工具,比如 Apifox 或者 Postman 等),这里我使用 Apifox 进行模拟 post 请求,我们修改一下user.service.ts中的create函数

  create(createUserDto: CreateUserDto) {return {code:200,result:'请求成功'};}

如果我们想要获取前端 Post 请求传过来参数,可以直接用@Body装饰器即可,同样的 get 请求的话则使用@Query,这里以 post 请求为例,我们回到user.controller.ts中的 create 函数里

@Post()create(@Body() createUserDto: CreateUserDto) {console.log(createUserDto);return this.userService.create(createUserDto);}

前端 post 携带 body 请求

如果你想直接获得 body 中的 username,你可以直接

 create(@Body('name') name: string) {console.log(name);//小月}

看到这有小伙伴就会问了CreateUserDto干啥的,很简单,它是用来描述数据形状的,也就是说它可以定义应该接受前端传来的什么参数,参数类型等,比如在 create-user.dto.ts 中可以这样定义

export class CreateUserDto {namename: string;
}

很多情况下我们需要获取前端传过来的请求头,其实在 nestjs 中获取请求头也很简单,只需要一个 Headers 装饰器即可

  @Post()create(@Body() createUserDto: CreateUserDto, @Headers() headers) {console.log(headers);return this.userService.create(createUserDto);}

关于装饰器还有很多,由于篇幅有限这里就不再过多介绍了,大家可以到官网自行查看呦~

九、Mysql

安装电脑匹配的mysql和mysql workbench

由于我的mac系统版本问题,我安装的都是8.0.19版本,当然没有任何问题的

1、TypeORM连接数据库

前置知识

首先,简单说一下什么是ORM?

我们如果直接使用Node.js操作mysql提供的接口, 那么编写的代码就比较底层, 例如一个插入数据代码:

// 向数据库中插入数据 
connection.query(`INSERT INTO posts (title, content) VALUES ('${title}', '${content}')`,(err, data) => {if (err) { console.error(err) } else {console.log(data) }
})

考虑到数据库表是一个二维表,包含多行多列,例如一个posts的表:

mysql> select * from posts;
+----+--------+------------+
| id | title       | content      |
+----+-------------+--------------+
|  1 | Nest.js入门 | 文章内容描述 |
+----+--------+------------+

每一行可以用一个JavaScript对象来表示, 比如第一行:

{id: 1,title:"Nest.js入门",content:"文章内容描述"
}

这就是传说中的ORM技术(Object-Relational Mapping),把关系数据库的表结构映射到对象上。

所以就出现了SequelizetypeORMPrisma这些ORM框架来做这个转换, (ps:Prisma呼声很高,喜欢探索的可以尝试一下)我们这里选择typeORM来操作数据库。 这样我们读写都是JavaScript对象,比如上面的插入语句就可以这样实现:

    return await this.userRepository.save(createUserDto);

接下来就是真正意义上的使用typeORM操作数据库, 首先我们要安装以下依赖包:

npm install @nestjs/typeorm typeorm mysql2 -S

连接数据库的方法:

app.mudule.ts文件中使用TypeOrmModule.forRoot

import { TypeOrmModule } from '@nestjs/typeorm';@Module({imports: [UserModule,TypeOrmModule.forRoot({type: 'mysql',host: 'localhost',port: 3306,username: 'root',password: 'lt851328',database: 'nestjs',entities: [__dirname + '/**/*.entity{.ts,.js}'],synchronize: true,}),],controllers: [AppController],providers: [AppService],
})

十、CRUD代码编写

接下来我们根据前端传来的参数对数据库进行一个简单的 crud 操作,注意这里只是演示,少了一些逻辑判断。 首先在user.module.ts中导入数据库相关东西

import { Module } from "@nestjs/common";
import { UserService } from "./user.service";
import { UserController } from "./user.controller";
import { UserEntity } from "./entities/user.entity";
import { TypeOrmModule } from "@nestjs/typeorm";
@Module({imports: [TypeOrmModule.forFeature([UserEntity])],controllers: [UserController],providers: [UserService],
})
export class UserModule {}

此时在create-user.dto.ts 定义一下接收前端传来的参数

export class CreateUserDto {username: string;password: string;
}

然后在user.service.ts进行数据库数据的操作,代码如下:

import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserEntity } from './entities/user.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';@Injectable()
export class UserService {constructor(@InjectRepository(UserEntity)private readonly userRepository: Repository<UserEntity>,) {}create(createUserDto: CreateUserDto) {console.log(createUserDto);return this.userRepository.save(createUserDto);}async findAll() {return await this.userRepository.find();}findOne(id: number) {return `This action returns a #${id} user`;}async update(id: number, updateUserDto: UpdateUserDto) {const db = this.userRepository.createQueryBuilder();return await db.update(updateUserDto).where({ id }).execute();}async remove(id: number) {const db = this.userRepository.createQueryBuilder();return await db.delete().where({ id }).execute();}
}

十一、统一接口规范

通过上面的一通操作,细心的小伙汁肯定发现了上面接口返回的数据是个什么玩意.要状态没状态,要描述没描述的,这样拿给前端前端不得揍死你。所以为了把最好的留给前端,我们还需要对接口返回进行一个统一数据封装。
在这里插入图片描述

一般接口返回的数据大致格式可能如下

{data:业务参数,code:状态码,describe:状态描述...
}

1、filter过滤器

首先我们使用命令新建一个过滤器,用来抛出我们需要返回给前端的错误码以告知前端传来的是错误请求

nest g filter common/filter/http-exception

然后修改一下http-exception.filter.ts

import {ExceptionFilter,Catch,ArgumentsHost,HttpException,
} from '@nestjs/common';
import { Request, Response } from 'express';@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {catch(exception: HttpException, host: ArgumentsHost) {const ctx = host.switchToHttp();const response = ctx.getResponse<Response>();const request = ctx.getRequest<Request>();const status = exception.getStatus();response.status(status).json({code: status,timestamp: new Date().toISOString(),path: request.url,});}
}
// This is a custom exception filter that will catch all HttpExceptions and return a JSON response with the status code, timestamp, and path of the request.
// The catch method takes two arguments: exception and host. exception is the HttpException that was thrown, and host is an ArgumentsHost object that provides access to the request and response objects.
// Inside the catch method, we switch to the HTTP context using the switchToHttp method and get the response and request objects using the getResponse and getRequest methods.

在 main.ts 中注册

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpExceptionFilter } from './common/filter/http-exception/http-exception.filter';
async function bootstrap() {const app = await NestFactory.create(AppModule);app.useGlobalFilters(new HttpExceptionFilter());await app.listen(3000);
}
bootstrap();

这时候我们随便找个接口抛出一个错误码试一下,就你了findAll方法

  async findAll() {throw new HttpException('错误的请求', 401);return await this.userRepository.find();}

然后我们再创建一个拦截器对请求成功的数据进行格式化

2、interceptor拦截器

然后我们再创建一个拦截器对请求成功的数据进行格式化

同样的使用

nest g interceptor common/interceptor/transform

创建一个拦截器,直接把官网示例抄过来transform.interceptor.ts

import {Injectable,NestInterceptor,ExecutionContext,CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';export interface Response<T> {data: T;
}@Injectable()
export class TransformInterceptor<T>implements NestInterceptor<T, Response<T>>
{intercept(context: ExecutionContext,next: CallHandler,): Observable<Response<T>> {return next.handle().pipe(map((data) => ({ code: 200, data, describe: '请求成功' })));}
}

以下是对这段代码的详细解释:

一、导入模块

import {Injectable,NestInterceptor,ExecutionContext,CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
  • Injectable:来自@nestjs/common,用于将一个类标记为可注入的服务。在这里,它用于标记TransformInterceptor类可以被 NestJS 的依赖注入系统管理。
  • NestInterceptorExecutionContextCallHandler也来自@nestjs/commonNestInterceptor是一个接口,用于定义拦截器。ExecutionContext提供了关于当前正在处理的请求的上下文信息,包括请求和响应对象等。CallHandler表示对路由处理函数的调用,可以用来控制请求的执行流程。
  • Observable来自rxjs,用于处理异步操作。在 NestJS 中,许多异步操作都是通过 Observable 来实现的。
  • map来自rxjs/operators,用于对 Observable 发出的值进行转换。

二、定义接口

export interface Response<T> {data: T;
}

这里定义了一个泛型接口Response,它表示一个响应对象,包含一个泛型类型的数据字段data

三、定义拦截器类

@Injectable()
export class TransformInterceptor<T>implements NestInterceptor<T, Response<T>>
{intercept(context: ExecutionContext,next: CallHandler,): Observable<Response<T>> {return next.handle().pipe(map((data) => ({ code: 200, data, describe: '请求成功' })));}
}
  • @Injectable()装饰器将TransformInterceptor类标记为可注入的服务,以便在 NestJS 的依赖注入系统中使用。
  • implements NestInterceptor<T, Response<T>>表示这个类实现了NestInterceptor接口,泛型参数T表示请求处理函数返回的数据类型,而Response<T>是拦截器处理后返回的响应类型。
  • intercept方法是拦截器的核心方法,它接收两个参数:ExecutionContext类型的contextCallHandler类型的next
    • context提供了关于当前请求的上下文信息,可以从中获取请求和响应对象等。
    • next是一个CallHandler,调用next.handle()会触发后续的请求处理流程,即执行路由处理函数。
  • return next.handle().pipe(map((data) => ({ code: 200, data, describe: '请求成功' })));这行代码首先调用next.handle()来触发后续的请求处理流程,然后使用pipemap操作符对处理结果进行转换。map操作符接收一个函数,这个函数将原始的处理结果data转换为一个包含状态码code、数据data和描述describe的对象,这里将状态码设置为 200,并添加了描述“请求成功”。最终返回一个新的Observable,其发出的值是经过转换后的响应对象。

这个拦截器的作用是在请求处理完成后,对响应数据进行统一的格式转换,添加状态码和描述信息,以便在整个应用中提供一致的响应格式。

最后

和过滤器一样在 main.ts 中注册

app.useGlobalInterceptors(new TransformInterceptor());

然后试一下查询接口,到这里我们就完成了返回结果的一个简单封装

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/55260.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】docker的存储

介绍 docker存储主要是涉及到3个方面&#xff1a; 第一个是容器启动时需要的镜像 镜像文件都是基于图层存储驱动来实现的&#xff0c;镜像图层都是只读层&#xff0c; 第二个是&#xff1a; 容器读写层&#xff0c; 容器启动后&#xff0c;docker会基于容器镜像的读层&…

服务器数据恢复—raid磁盘故障导致数据库文件损坏的数据恢复案例

服务器存储数据恢复环境&故障&#xff1a; 存储中有一组由3块SAS硬盘组建的raid。上层win server操作系统层面划分了3个分区&#xff0c;数据库存放在D分区&#xff0c;备份存放在E分区。 RAID中一块硬盘的指示灯亮红色&#xff0c;D分区无法识别&#xff1b;E分区可识别&a…

【理论科学与实践技术】数学与经济管理中的学科与实用算法

在现代商业环境中&#xff0c;数学与经济管理的结合为企业提供了强大的决策支持。包含一些主要学科&#xff0c;包括数学基础、经济学模型、管理学及风险管理&#xff0c;相关的实用算法和这些算法在中国及全球知名企业中的实际应用。 一、数学基础 1). 发现人及著名学者 发…

开源项目 - 交通工具检测 yolo v3 物体检测 单车检测 车辆检测 飞机检测 火车检测 船只检测

开源项目 - 交通工具检测 yolo v3 物体检测 单车检测 车辆检测 飞机检测 火车检测 船只检测 开源项目地址&#xff1a;https://gitcode.net/EricLee/yolo_v3 示例&#xff1a;

前端学习第二天笔记 CSS选择 盒子模型 浮动 定位 CSS3新特性 动画 媒体查询 精灵图雪碧图 字体图标

CSS学习 CSS选择器全局选择器元素选择器类选择器ID选择器合并选择器 选择器的优先级字体属性背景属性文本属性表格属性表格边框折叠边框表格文字对齐表格填充表格颜色 关系选择器后代选择器子代选择器相邻兄弟选择器通用兄弟选择器 CSS盒子模型弹性盒子模型父元素上的属性flex-…

大厂面试真题-说一下Mybatis的缓存

首先看一下原理图 Mybatis提供了两种缓存机制&#xff1a;一级缓存&#xff08;L1 Cache&#xff09;和二级缓存&#xff08;L2 Cache&#xff09;&#xff0c;旨在提高数据库查询的性能&#xff0c;减少数据库的访问次数。注意查询的顺序是先二级缓存&#xff0c;再一级缓存。…

主存储器——随机存取存储器RAM

静态RAM 双稳态触发器 一、工作特性 两种稳定状态&#xff1a; 双稳态触发器具有两个稳定的输出状态&#xff0c;通常表示为 0 和 1&#xff08;或低电平和高电平&#xff09;。这两个状态可以长期保持&#xff0c;即使在没有输入信号的情况下&#xff0c;也不会自发地改变。 例…

初识TCP/IP协议

回顾上文 来回顾一下TCP协议的特性&#xff0c;有一道比较经典的题&#xff1a;如何使用UDP实现可靠传输&#xff0c;通过应用程序的代码&#xff0c;完成可靠传输的过程&#xff1f; 原则&#xff0c;TCO有啥就吹啥&#xff0c;引入滑动窗口&#xff0c;引入流量控制&#x…

基于 Qwen2.5-0.5B 微调训练 Ner 命名实体识别任务

一、Qwen2.5 & 数据集 Qwen2.5 是 Qwen 大型语言模型的最新系列&#xff0c;参数范围从 0.5B 到 72B 不等。 对比 Qwen2 最新的 Qwen2.5 进行了以下改进&#xff1a; 知识明显增加&#xff0c;并且大大提高了编码和数学能力。在指令跟随、生成长文本&#xff08;超过 8K…

前台项目启动/打包报错 Error: error:0308010C:digital envelope routines::unsupported

在package.json中修改启动/打包语句 如图&#xff0c;我这里是打包时候报错&#xff0c;就在build里前面加上 set NODE_OPTIONS--openssl-legacy-provider && 再次打包&#xff0c;成功。

Unity 2D RPG Kit 学习笔记

学习资料&#xff1a; B站教学视频&#xff1a;https://www.bilibili.com/video/BV1dC4y1o7A5?p1&vd_source707ec8983cc32e6e065d5496a7f79ee6 2D RPG Kit Documentation.pdf文档 1、2D RPG Kit Documentation文档 1.1、Scenes/TitleScreen 开始菜单工程 1.2、https://it…

闭源与开源嵌入模型比较以及提升语义搜索效果的技术探讨

上图为执行语义搜索前的聚类演示 &#xff0c;嵌入技术是自然语言处理的核心组成部分。虽然嵌入技术的应用范围广泛&#xff0c;但在检索应用中的语义搜索仍是其最常见的用途之一。 尽管知识图谱等可以提升检索的准确率和效率&#xff0c;但标准向量检索技术仍然具有其实用价值…

「安装」 Windows下安装CUDA和Pytorch

「安装」 Windows下安装CUDA和Pytorch 文章目录 「安装」 Windows下安装CUDA和PytorchMac、Linux、云端Windows安装CUDA安装miniconda安装PyTorch测试总结 其他 Mac、Linux、云端 Mac、Linux、云端安装Miniconda和Pytorch的方法参考其他资料。 Windows 下面进行Windows下安装…

TDengine 流计算与窗口机制的深度解析:揭示计数窗口的关键作用

在 TDengine 3.2.3.0 版本中&#xff0c;我们针对流式计算新增了计数窗口&#xff0c;进一步优化了流式数据处理的能力。本文将为大家解读流式计算与几大窗口的关系&#xff0c;并针对新增的计数窗口进行详细的介绍&#xff0c;帮助大家进一步了解 TDengine 流式计算&#xff0…

基于Hive和Hadoop的病例分析系统

本项目是一个基于大数据技术的医疗病历分析系统&#xff0c;旨在为用户提供全面的病历信息和深入的医疗数据分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 Spark…

uniapp中实现评分组件,多用于购买商品后,对商品进行评价等场景

前言 uni-rate是uniapp框架中提供的一个评分组件。它可以用于用户评价、打分等场景。uni-rate组件可以根据设定的星星总数&#xff0c;展示用户评分的效果&#xff0c;用户可以通过点击星星或滑动星星的方式进行评分。同时&#xff0c;uni-rate组件也支持自定义星星图标、星星…

AI助手——合理利用AI写作的相关方法

引言 概述AI助手的出现与应用现状 AI助手的出现是随着人工智能技术的不断进步而逐渐成为现实。AI助手是利用人工智能技术开发的智能辅助工具&#xff0c;可以在多个领域提供帮助和支持。在写作领域&#xff0c;AI助手的应用越来越广泛。 AI助手可以帮助写作者更高效地完成文本…

新品 | Teledyne FLIR IIS 推出Forge 1GigE SWIR 短波红外工业相机系列

近日&#xff0c;51camera的合作伙伴Teledyne FLIR IIS推出了新品Forge 1GigE SWIR 130万像素的红外相机。 Forge 1GigE SWIR系列的首款相机配备宽频带、高灵敏度的Sony SenSWIR™️ 130万像素IMX990 InGaAs传感器。这款先进的传感器采用5um像素捕捉可见光和SWIR光谱&#xff…

大语言模型知识点分享

1 目前主流的开源模型体系有哪些&#xff1f; Prefix Decoder 系列模型 核心点&#xff1a; 输入采用双向注意力机制&#xff0c;输出为单向注意力。双向注意力意味着输入的每个部分都可以关注到输入的所有其他部分&#xff0c;这在理解上下文时具有很强的优势。 代表模型&a…