学 Resolver 最好要有 GraphQL 的基础知识,最好要是自己实践过的。
我们知道 GraphQL 本质就是使用 DSL 在前后端进行统一的验证,resolver 就是在服务端的校验成功之后需要调用的函数。当然生成 DSL 的 schema 都是它。
本质
Resolvers 本质是一个函数,干具体事情的函数,类似于 controller 层的路由注释的哈数。Resolver 不在是路由的注释,而是查询的注释
作用
Resolver 的作用
- 生成 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
}