NestJS基础 Resolvers

2,054 阅读2分钟

学 Resolver 最好要有 GraphQL 的基础知识,最好要是自己实践过的。

我们知道 GraphQL 本质就是使用 DSL 在前后端进行统一的验证,resolver 就是在服务端的校验成功之后需要调用的函数。当然生成 DSL 的 schema 都是它。

本质

Resolvers 本质是一个函数,干具体事情的函数,类似于 controller 层的路由注释的哈数。Resolver 不在是路由的注释,而是查询的注释

作用

Resolver 的作用

  1. 生成 Schema

GrahpQL 中的resolver类型

  • type Query
  • type Mutation
  • type Subscription
  • type CustomTpye

自定义类型在,list 中可以通过 type-graphql 来描述。

下面是一个 schema 对应的模型,使用了装饰器语法,交给 resolers 之后 nestjs 会自动的生成 schema 进行处理。

import { Field, ID, ObjectType } from 'type-graphql';

@ObjectType()
export class Recipe {
  @Field(type => ID)
  id: string;

  @Field()
  title: string;

  @Field({ nullable: true })
  description?: string;

  @Field()
  creationDate: Date;

  @Field(type => [String])
  ingredients: string[];
}

生成的 schema 类型

type Recipe {
  id: ID!
  title: String!
  description: String
  creationDate: Date!
  ingredients: [String!]!
}

自定义一个参数类型

import { Max, Min } from 'class-validator';
import { ArgsType, Field, Int } from 'type-graphql';

@ArgsType()
export class RecipesArgs {
  @Field(type => Int)
  @Min(0)
  skip: number = 0;

  @Field(type => Int)
  @Min(1)
  @Max(50)
  take: number = 25;
}
type Query {
  recipe(id: String!): Recipe!
  recipes(skip: Int = 0, take: Int = 25): [Recipe!]!
}

自定义 input 类型

import { IsOptional, Length, MaxLength } from 'class-validator';
import { Field, InputType } from 'type-graphql';

@InputType()
export class NewRecipeInput {
  @Field()
  @MaxLength(30)
  title: string;

  @Field({ nullable: true })
  @IsOptional()
  @Length(30, 255)
  description?: string;

  @Field(type => [String])
  ingredients: string[];
}

代码优先

NestJS 中提供了两种方式写 GraphQL:

  • TypeScript 映射到 Schema
  • Schema 到 TypeScript

实际上我们是需要 Schema 因为 GraphQL 中的一些特性(),必须使用 Schema 来定义。所以我们使用了代码优先,我们也必须生成 Schema。

@nestjs/graphql 工具包

工具包提供了各种修饰器,来让我们将一个 class 类映射为一个 Schema。

import { Field, Int, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class Article {
  @Field(type => Int)
  id: number;

  @Field({ nullable: true })
  title?: string;

  @Field({ nullable: true })
  content?: string;
}

映射到 Schema 是这样的

type Author {
  id: Int!
  title: String
  content: String
}

@ObjectType Schema 类型声明器

使用 @ObjectType 的声明器是一个

@Field 字段装饰器

@Field装饰的表示一个字段,它可以接受一个类型函数或者对象(对象内部可以包含类型函数)作为参数。

  • 函数,以 type 参数,函数的返回值类型,即对应的 Schema 值。
  • 对象
    • nullable: 是否可为空
    • description: 描述字符串

@nestjs/graphql

这个包导出了:

  • @Resolver
  • @ResolveField
  • @Args
  • ...
@Resolver(of => Author)
export class AuthorsResolver {
  constructor(
    private authorsService: AuthorsService,
    private postsService: PostsService,
  ) {}

  @Query(returns => Author)
  async author(@Args('id', { type: () => Int }) id: number) {
    return this.authorsService.findOneById(id);
  }

  @ResolveField()
  async posts(@Parent() author: Author) {
    const { id } = author;
    return this.postsService.findAll({ authorId: id });
  }
}

查询 @Query 对应 type Query

@Query(returns => Author)
async author(@Args('id', { type: () => Int }) id: number) {
  return this.authorsService.findOneById(id);
}

对应的 Schema:

type Query {
  author(id: Int!): Author
}