简介
GraphQL 是一种用于 API 的查询语言和运行时环境。它提供了一种更有效、更强大和更灵活的替代 REST,可以满足不同客户端的数据请求需求。Nest.js 是一款基于 Node.js 平台的现代化 Web 开发框架,它提供了模块化、面向切面编程、依赖注入和 MVC 等高级特性。
在本文中,我们将探讨如何在 Nest.js 应用程序中使用 GraphQL,包括安装和配置、定义数据模型、声明查询和变异等内容。我们将借助第三方库 @nestjs/graphql
和 graphql-tools
来完成 GraphQL 的实现。
安装和配置
在开始之前,请确保已经安装了 Node.js 和 Nest.js,它们分别在官方网站
安装完毕后,我们可以在终端中使用以下命令创建一个新的 Nest.js 应用程序:
$ nest new myapp
然后,我们可以在应用程序的根目录中安装 @nestjs/graphql
和 graphql-tools
:
$ npm install @nestjs/graphql graphql-tools
接下来,我们需要在 app.module.ts
文件中导入和配置 GraphQLModule
,如下所示:
// javascriptcn.com 代码示例 import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; @Module({ imports: [ GraphQLModule.forRoot({ autoSchemaFile: 'schema.gql', }), ], }) export class AppModule {}
这里,我们使用 GraphQLModule.forRoot()
方法来配置 GraphQLModule
的选项。其中 autoSchemaFile
用来指定保存 GraphQL 模式的文件名,后面我们将会详细讲解。
定义数据模型
在使用 GraphQL 时,我们首先需要定义数据模型。在 Nest.js 中使用 GraphQL,我们通常会创建一个 input
类来表示客户端传入的数据,一个 type
类来表示输出给客户端的数据。
在 src
目录下,创建一个名为 cats
的模块,包括 models
和 resolvers
两个子模块。在 models
子模块下,我们创建名为 cat.input.ts
和 cat.type.ts
文件,分别声明 CatInput
和 CatType
类型。具体代码如下:
// javascriptcn.com 代码示例 // cat.input.ts import { InputType, Field } from '@nestjs/graphql'; @InputType() export class CatInput { @Field() readonly name: string; @Field() readonly age: number; @Field() readonly breed: string; } // cat.type.ts import { ObjectType, Field, Int } from '@nestjs/graphql'; @ObjectType() export class CatType { @Field(() => Int) readonly id: number; @Field() readonly name: string; @Field() readonly age: number; @Field() readonly breed: string; }
在上面的代码中,我们通过 @InputType()
和 @ObjectType()
装饰器来定义 CatInput
和 CatType
类型。@Field()
装饰属性和/或方法,以指定 GraphQL 类型。在 CatType
类型中,我们还定义了一个 ID 字段,用于区分每只猫。此 ID 字段不需要从客户端传入,因此不需要在 CatInput
类型中定义。
声明查询
在定义数据模型后,我们需要声明查询语句。在 Nest.js 中使用 GraphQL,我们需要在 resolvers
子模块中创建一个新的 cats.resolver.ts
文件。在这个文件中,我们使用 @Query()
装饰器来定义一个名为 getCats
的查询,查询所有猫的信息。具体代码如下:
// javascriptcn.com 代码示例 import { Resolver, Query, Args, Mutation } from '@nestjs/graphql'; import { CatType } from './cat.type'; import { CatInput } from './cat.input'; @Resolver() export class CatsResolver { private readonly cats: CatType[] = []; @Query(() => [CatType]) async getCats() { return this.cats; } @Mutation(() => CatType) async createCat(@Args('catInput') catInput: CatInput) { const cat = { id: this.cats.length + 1, name: catInput.name, age: catInput.age, breed: catInput.breed, }; this.cats.push(cat); return cat; } }
在上面的代码中,我们首先在 @Resolver()
装饰器中声明该类是一个 GraphQL 解析器。然后,我们声明了一个名为 getCats()
的查询函数,当客户端进一步指定查询猫信息时,调用这个函数。我们也声明了一个 createCat()
函数,用于将新的猫信息添加到 cats
数组中。
注意 @Query(() => [CatType])
中的 CatType
是在上一步中定义的输出类型。
生成 GraphQL 模式
在定义数据模型和查询解析器后,我们需要使用 graphql-tools
来生成可执行的 GraphQL 模式。我们通过 buildSchema
方法来将上述定义和声明编译为 GraphQL 模式。为此,我们在 src/cats/cats.service.ts
文件中创建一个新的 CatsService
类,具体代码如下:
// javascriptcn.com 代码示例 import { Injectable } from '@nestjs/common'; import { CatType } from './models/cat.type'; import { CatInput } from './models/cat.input'; import { CatsResolver } from './resolvers/cats.resolver'; import { makeExecutableSchema } from '@graphql-tools/schema'; @Injectable() export class CatsService { private readonly resolvers: CatsResolver = new CatsResolver(); private readonly schema = makeExecutableSchema({ typeDefs: ` type Query { getCats: [CatType] } type Mutation { createCat(catInput: CatInput!): CatType } type CatType { id: Int! name: String! age: Int! breed: String! } input CatInput { name: String! age: Int! breed: String! } `, resolvers: { Query: { getCats: this.resolvers.getCats.bind(this.resolvers), }, Mutation: { createCat: this.resolvers.createCat.bind(this.resolvers), }, }, }); getSchema() { return this.schema; } }
在代码中,我们使用了 makeExecutableSchema
方法来生成可执行的 GraphQL 模式。
typeDefs
用于声明我们定义的 CatType
和 CatInput
类型。Query
子类型用于声明我们定义的查询方法,如 getCats
。Mutation
子类型用于声明我们定义的变异方法,如 createCat
。resolvers
对象把 getCats
方法和 createCat
方法绑定到查询解析器中。
getSchema
方法被注入为 Nest.js 服务的一个方法,任何请求使用我们生成的可执行 schema 处理。它将被用于在 HTTP 底层 API 中注册 GraphQL 模式。
在 app.module.ts
的 GraphQLModule.forRoot()
方法中,我们使用 SchemaModule
模块配置,如下所示:
// javascriptcn.com 代码示例 import { Module } from '@nestjs/common'; import { CatsModule } from './cats/cats.module'; import { GraphQLModule } from '@nestjs/graphql'; import { CatsService } from './cats/cats.service'; @Module({ imports: [ CatsModule, GraphQLModule.forRootAsync({ useFactory: async (catsService: CatsService) => ({ autoSchemaFile: 'schema.gql', playground: true, schema: await catsService.getSchema(), }), inject: [CatsService], }), ], }) export class AppModule {}
在 GraphQLModule.forRootAsync()
中,我们使用 useFactory
方法注入 CatsService
服务,并且将 schema
配置为 CatsService.getSchema()
方法生成的 schema。让我们考虑一下 autoSchemaFile
属性。这个属性只是把它合成的 GraphQL schema 输出到它指定的文件。如果使用 useSchema
配置 GraphQLModule
schema,则 autoSchemaFile
选项将被忽略。
使用 Playground 来测试
最后,我们需要启动应用程序,并使用 GraphQL Playground 来测试我们的查询和变异。我们使用以下命令启动应用程序:
$ npm run start
在浏览器中打开 http://localhost:3000/graphql
,我们就可以进入 GraphQL Playground 了。此时,我们可以打开 DOCS
标签页来查看我们定义的查询和变异方法。具体代码如下:
// javascriptcn.com 代码示例 query { getCats { id name age } } mutation { createCat( catInput: { name: "Kitty" age: 3 breed: "Siamese" } ) { id name age breed } }
以上查询可以分别用于获取所有猫的信息和添加一只新的猫。GraphQL Playground 会在右侧的 RESULT
标签页中显示响应的 JSON 数据。
总结
在本篇文章中,我们介绍了如何在 Nest.js 中集成 GraphQL。我们通过安装和配置 @nestjs/graphql
和 graphql-tools
帮助来使用 GraphQL。我们也定义了数据模型,声明了查询和变异方法。最后,我们使用 GraphQL Playground 来测试我们的查询和变异方法。如果您还没有使用 GraphQL,我希望此文可以帮助您了解更多关于 GraphQL 的知识。如果您对此有任何疑问或意见,请在评论中留言。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6549ccdd7d4982a6eb406505