【飞机@duoteJG】多特工作室杰哥版权所有,禁止转载
在本文中,您将在后端使用 GT江湖GraphQL 和 Node.js 构建一个飞鸟新圣全栈应用程序。同时,我们的前端盘口数据对接将使用该graphql-request库在我们的后端执行网络操作。
- 为什么使用
graphql-request
TypeScript?
每当开发人员使用 Apollo 构建 GraphQL 服务器时,该库都会生成一个“前端”,如下所示:
该接口允许用户通过代码向服务器发出查询或变异请求。然而,让我们来谈谈房间里的大象:它看起来不太友好。由于前端没有任何按钮或任何有用的界面元素,因此许多用户可能很难在您的应用程序中导航。因此,这会缩小您的用户群。那么我们如何解决这个问题呢?
这就是graphql-request进来的地方。它是一个开源库,允许用户在 GraphQL 服务器上执行查询。它具有以下特点:
- 轻量级——这个库被压缩了超过 21 KB,确保你的应用程序保持高性能
- 基于 Promise 的 API——这带来了对异步应用程序的支持
- TypeScript 支持——
graphql-request
是众多支持 TypeScript 的库之一。Typescript 的一个主要优点是它允许编写稳定且可预测的代码
例如,看下面的程序:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">myNumber</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-literal-color)">9</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//here, myNumber is an integer</span>
<span style="color:var(--syntax-name-color)">myNumber</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">hello</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//now it is a string.</span>
<span style="color:var(--syntax-name-color)">myNumber</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">myNumber</span> <span style="color:var(--syntax-error-color)">+</span> <span style="color:var(--syntax-literal-color)">10</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//even though we are adding a string to an integer,</span>
<span style="color:var(--syntax-comment-color)">//JavaScript won't return an error. In the real world, it might bring unexpected outputs.</span>
<span style="color:var(--syntax-comment-color)">//However, in Typescript, we can tell the compiler..</span>
<span style="color:var(--syntax-comment-color)">//what data types we need to choose.</span>
<span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">myNumber</span><span style="color:var(--syntax-text-color)">:</span><span style="color:var(--syntax-name-color)">number</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-literal-color)">39</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//tell TS that we want to declare an integer.</span>
<span style="color:var(--syntax-name-color)">myNumber</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-literal-color)">9</span><span style="color:var(--syntax-error-color)">+</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">hello</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//returns an error. Therefore, it's easier to debug the program</span>
<span style="color:var(--syntax-comment-color)">//this promises stability and security. </span>
</code></span></span>
在本文中,我们将使用 GraphQL 和 TypeScript 构建一个全栈应用程序。在这里,我们将使用该apollo-server-express包来构建一个后端服务器。此外,对于前端,我们将使用 Next 并graphql-request
使用我们的 GraphQL API。
构建我们的服务器
项目初始化
要初始化一个空白 Node.js 项目,请运行以下终端命令:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-name-color)">mkdir</span> <span style="color:var(--syntax-name-color)">graphql</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">ts</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">tutorial</span> #<span style="color:var(--syntax-name-color)">create</span> <span style="color:var(--syntax-name-color)">project</span> <span style="color:var(--syntax-name-color)">folder</span>
<span style="color:var(--syntax-name-color)">cd</span> <span style="color:var(--syntax-name-color)">graphql</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">ts</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">tutorial</span>
<span style="color:var(--syntax-name-color)">npm</span> <span style="color:var(--syntax-name-color)">init</span> <span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">y</span> #<span style="color:var(--syntax-name-color)">initialize</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">app</span>
</code></span></span>
完成后,我们现在必须告诉 Node 我们需要在代码库中使用 TypeScript:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>#<span style="color:var(--syntax-name-color)">configure</span> <span style="color:var(--syntax-name-color)">our</span> <span style="color:var(--syntax-name-color)">Typescript</span><span style="color:var(--syntax-text-color)">:</span>
<span style="color:var(--syntax-name-color)">npx</span> <span style="color:var(--syntax-name-color)">tsc</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">init</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">rootDir</span> <span style="color:var(--syntax-name-color)">app</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">outDir</span> <span style="color:var(--syntax-name-color)">dist</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">esModuleInterop</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">resolveJsonModule</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">lib</span> <span style="color:var(--syntax-name-color)">es6</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">module</span> <span style="color:var(--syntax-name-color)">commonjs</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">allowJs</span> <span style="color:var(--syntax-declaration-color)">true</span> <span style="color:var(--syntax-error-color)">--</span><span style="color:var(--syntax-name-color)">noImplicitAny</span> <span style="color:var(--syntax-declaration-color)">true</span>
<span style="color:var(--syntax-name-color)">mkdir</span> <span style="color:var(--syntax-name-color)">app</span> #<span style="color:var(--syntax-name-color)">our</span> <span style="color:var(--syntax-name-color)">main</span> <span style="color:var(--syntax-name-color)">code</span> <span style="color:var(--syntax-name-color)">folder</span>
<span style="color:var(--syntax-name-color)">mkdir</span> <span style="color:var(--syntax-name-color)">dist</span> #<span style="color:var(--syntax-name-color)">Typescript</span> <span style="color:var(--syntax-name-color)">will</span> <span style="color:var(--syntax-name-color)">use</span> <span style="color:var(--syntax-declaration-color)">this</span> <span style="color:var(--syntax-name-color)">folder</span> <span style="color:var(--syntax-name-color)">to</span> <span style="color:var(--syntax-name-color)">compile</span> <span style="color:var(--syntax-name-color)">our</span> <span style="color:var(--syntax-name-color)">program</span><span style="color:var(--syntax-text-color)">.</span>
</code></span></span>
接下来,安装这些依赖项:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>#<span style="color:var(--syntax-name-color)">development</span> <span style="color:var(--syntax-name-color)">dependencies</span><span style="color:var(--syntax-text-color)">.</span> <span style="color:var(--syntax-name-color)">Will</span> <span style="color:var(--syntax-name-color)">tell</span> <span style="color:var(--syntax-name-color)">Node</span> <span style="color:var(--syntax-name-color)">that</span> <span style="color:var(--syntax-name-color)">we</span> <span style="color:var(--syntax-name-color)">will</span> <span style="color:var(--syntax-name-color)">use</span> <span style="color:var(--syntax-name-color)">Typescript</span>
<span style="color:var(--syntax-name-color)">npm</span> <span style="color:var(--syntax-name-color)">install</span> <span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">d</span> <span style="color:var(--syntax-name-color)">ts</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">node</span> <span style="color:var(--syntax-text-color)">@</span><span style="color:var(--syntax-name-color)">types</span><span style="color:var(--syntax-string-color)">/node typescript @types/</span><span style="color:var(--syntax-name-color)">express</span> <span style="color:var(--syntax-name-color)">nodemon</span>
#<span style="color:var(--syntax-name-color)">Installing</span> <span style="color:var(--syntax-name-color)">Apollo</span> <span style="color:var(--syntax-name-color)">Server</span> <span style="color:var(--syntax-name-color)">and</span> <span style="color:var(--syntax-name-color)">its</span> <span style="color:var(--syntax-name-color)">associated</span> <span style="color:var(--syntax-name-color)">modules</span><span style="color:var(--syntax-text-color)">.</span> <span style="color:var(--syntax-name-color)">Will</span> <span style="color:var(--syntax-name-color)">help</span> <span style="color:var(--syntax-name-color)">us</span> <span style="color:var(--syntax-name-color)">build</span> <span style="color:var(--syntax-name-color)">our</span> <span style="color:var(--syntax-name-color)">GraphQL</span>
#<span style="color:var(--syntax-name-color)">server</span>
<span style="color:var(--syntax-name-color)">npm</span> <span style="color:var(--syntax-name-color)">install</span> <span style="color:var(--syntax-name-color)">apollo</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">server</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">express</span> <span style="color:var(--syntax-name-color)">apollo</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">server</span><span style="color:var(--syntax-error-color)">-</span><span style="color:var(--syntax-name-color)">core</span> <span style="color:var(--syntax-name-color)">express</span> <span style="color:var(--syntax-name-color)">graphql</span>
</code></span></span>
完成此步骤后,导航到您的app
文件夹。在这里,创建以下文件:
-
index.ts
: 我们的主文件。这将执行并运行我们的 Express GraphQL 服务器 -
dataset.ts
:这将作为我们的数据库,将提供给客户 -
Resolvers.ts
:该模块将处理用户命令。我们将在本文后面了解解析器 -
Schema.ts
:顾名思义,这个文件将存储向客户端发送数据所需的原理图
最后,您的文件夹结构应如下所示:
创建我们的数据库
在本节中,我们将创建一个虚拟数据库,用于发送请求的数据。为此,请转到app/dataset.ts
并编写以下代码:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">let</span> <span style="color:var(--syntax-name-color)">people</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-text-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">number</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-text-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">string</span> <span style="color:var(--syntax-text-color)">}[]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">[</span>
<span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Cassie</span><span style="color:var(--syntax-string-color)">"</span> <span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">2</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Rue</span><span style="color:var(--syntax-string-color)">"</span> <span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">3</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Lexi</span><span style="color:var(--syntax-string-color)">"</span> <span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">];</span>
<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-name-color)">people</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>
- 首先,我们创建了一个对象数组,称为
people
- 该数组将有两个字段:
id
类型number
和name
类型string
定义我们的模式
在这里,我们现在将为我们的 GraphQL 服务器创建一个模式。
简而言之,GraphQL 模式是对客户端可以从 API 请求的数据集的描述。这个概念类似于Mongoose 库的概念。要构建架构,请导航到该app/Schema.ts
文件。在那里,编写以下代码:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">gql</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">apollo-server-express</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//will create a schema</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">Schema</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">gql</span><span style="color:var(--syntax-string-color)">`
type Person {
id: ID!
name: String
}
#handle user commands
type Query {
getAllPeople: [Person] #will return multiple Person instances
getPerson(id: Int): Person #has an argument of 'id`</span> <span style="color:var(--syntax-declaration-color)">of</span> <span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Integer</span><span style="color:var(--syntax-text-color)">.</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-string-color)">`;
export default Schema;
//export this Schema so we can use it in our project
</span></code></span></span>
让我们逐段分解这段代码:
- 该
Schema
变量包含我们的 GraphQL 架构 - 首先,我们创建了一个
Person
模式。它将有两个字段:id
类型ID
和name
类型String
- 稍后,我们指示 GraphQL,如果客户端运行命令,服务器将返回一个对象
getAllPeople
数组Person
- 此外,如果用户使用该
getPerson
命令,GraphQL 将返回单个Person
实例
创建解析器
现在我们已经编写了模式,下一步是定义解析器。简单来说,解析器是一组为 GraphQL 查询生成响应的函数。换句话说,解析器充当 GraphQL 查询处理程序。
在Resolvers.ts
中,编写以下代码:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">people</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./dataset</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//get all of the available data from our database.</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">Resolvers</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">Query</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">getAllPeople</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">people</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-comment-color)">//if the user runs the getAllPeople command</span>
<span style="color:var(--syntax-comment-color)">//if the user runs the getPerson command:</span>
<span style="color:var(--syntax-name-color)">getPerson</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">_</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">any</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">any</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">console</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">log</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-comment-color)">//get the object that contains the specified ID.</span>
<span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">people</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">find</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">person</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">person</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">default</span> <span style="color:var(--syntax-name-color)">Resolvers</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>
- 在这里,我们创建了一个
Query
对象来处理所有进入服务器的查询 - 如果用户执行
getAllPeople
命令,程序将返回我们数据库中存在的所有对象 - 此外,该
getPerson
命令需要一个参数id
。这将返回一个Person
具有匹配 ID 的实例 - 最后,我们导出了我们的解析器,以便它可以与我们的应用程序链接
配置我们的服务器
我们快完成了!现在我们已经构建了模式和解析器,下一步是将它们链接在一起。在index.js
中,编写以下代码块:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">ApolloServer</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">apollo-server-express</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">Schema</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./Schema</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">Resolvers</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./Resolvers</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">express</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">express</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">ApolloServerPluginDrainHttpServer</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">apollo-server-core</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-name-color)">http</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">http</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">startApolloServer</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">schema</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">any</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">resolvers</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">any</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">app</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">express</span><span style="color:var(--syntax-text-color)">();</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">httpServer</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">http</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">createServer</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">app</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">server</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-name-color)">ApolloServer</span><span style="color:var(--syntax-text-color)">({</span>
<span style="color:var(--syntax-name-color)">typeDefs</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">schema</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-name-color)">resolvers</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-comment-color)">//tell Express to attach GraphQL functionality to the server</span>
<span style="color:var(--syntax-name-color)">plugins</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">ApolloServerPluginDrainHttpServer</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">httpServer</span> <span style="color:var(--syntax-text-color)">})],</span>
<span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-name-color)">any</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">server</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">start</span><span style="color:var(--syntax-text-color)">();</span> <span style="color:var(--syntax-comment-color)">//start the GraphQL server.</span>
<span style="color:var(--syntax-name-color)">server</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">applyMiddleware</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">app</span> <span style="color:var(--syntax-text-color)">});</span>
<span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-text-color)">Promise</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-declaration-color)">void</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">resolve</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
<span style="color:var(--syntax-name-color)">httpServer</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">listen</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">port</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">4000</span> <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-name-color)">resolve</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-comment-color)">//run the server on port 4000</span>
<span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-name-color)">console</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">log</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`Server ready at http://localhost:4000</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">server</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">graphqlPath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-comment-color)">//in the end, run the server and pass in our Schema and Resolver.</span>
<span style="color:var(--syntax-name-color)">startApolloServer</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">Schema</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">Resolvers</span><span style="color:var(--syntax-text-color)">);</span>
</code></span></span>
让我们测试一下!要运行代码,请使用此 Bash 命令:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>npx nodemon app/index.ts
</code></span></span>
这将在localhost:4000/graphql
URL 上创建一个服务器。
在这里,您可以在 UI 中查看可用的架构:
动图
编辑
这意味着我们的代码有效!我们所有的 GraphQL 查询都将进入操作面板。
要查看它的实际效果,请在此框中键入此代码段:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>#<span style="color:var(--syntax-name-color)">make</span> <span style="color:var(--syntax-name-color)">a</span> <span style="color:var(--syntax-name-color)">query</span><span style="color:var(--syntax-text-color)">:</span>
<span style="color:var(--syntax-name-color)">query</span> <span style="color:var(--syntax-text-color)">{</span>
#<span style="color:var(--syntax-declaration-color)">get</span> <span style="color:var(--syntax-name-color)">all</span> <span style="color:var(--syntax-declaration-color)">of</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">people</span> <span style="color:var(--syntax-name-color)">available</span> <span style="color:var(--syntax-declaration-color)">in</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">server</span>
<span style="color:var(--syntax-name-color)">getAllPeople</span> <span style="color:var(--syntax-text-color)">{</span>
#<span style="color:var(--syntax-name-color)">procure</span> <span style="color:var(--syntax-name-color)">their</span> <span style="color:var(--syntax-name-color)">IDs</span> <span style="color:var(--syntax-name-color)">and</span> <span style="color:var(--syntax-name-color)">names</span><span style="color:var(--syntax-text-color)">.</span>
<span style="color:var(--syntax-name-color)">id</span>
<span style="color:var(--syntax-name-color)">name</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>
要查看结果,请单击“运行”按钮:我们甚至可以通过查询搜索特定实体getPerson
:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-name-color)">query</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">$getPersonId</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">Int</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span> #<span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">argument</span> <span style="color:var(--syntax-name-color)">will</span> <span style="color:var(--syntax-name-color)">be</span> <span style="color:var(--syntax-declaration-color)">of</span> <span style="color:var(--syntax-declaration-color)">type</span> <span style="color:var(--syntax-name-color)">Integer</span>
<span style="color:var(--syntax-name-color)">getPerson</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
#<span style="color:var(--syntax-declaration-color)">get</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">person</span> <span style="color:var(--syntax-declaration-color)">with</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">ID</span> <span style="color:var(--syntax-declaration-color)">of</span> <span style="color:var(--syntax-literal-color)">1</span>
<span style="color:var(--syntax-name-color)">name</span>
<span style="color:var(--syntax-name-color)">id</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>
创建突变
在 GraphQL 世界中,突变是对数据库执行副作用的命令。常见的例子包括:
- 将用户添加到数据库 - 当客户注册网站时,用户执行突变以将他们的数据保存在他们的数据库中
- 编辑或删除对象——如果用户修改或删除数据库中的数据,他们实质上是在服务器上创建一个突变
要处理突变,请转到您的Schema.ts
模块。在这里,在Schema
变量中,添加以下代码行:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">Schema</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">gql</span><span style="color:var(--syntax-string-color)">`
#other code..
type Mutation {
#the addPerson commmand will accept an argument of type String.
#it will return a 'Person' instance.
addPerson(name: String): Person
}
`</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>
我们的下一步是创建一个解析器来处理这个突变。为此,在Resolvers.ts
文件中添加以下代码块:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">Resolvers</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">Query</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-comment-color)">//..further code..</span>
<span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-comment-color)">//code to add:</span>
<span style="color:var(--syntax-comment-color)">//all our mutations go here.</span>
<span style="color:var(--syntax-name-color)">Mutation</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-comment-color)">//create our mutation:</span>
<span style="color:var(--syntax-name-color)">addPerson</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">_</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">any</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-declaration-color)">any</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">newPerson</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">people</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span> <span style="color:var(--syntax-error-color)">+</span> <span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-comment-color)">//id field</span>
<span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">args</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-comment-color)">//name field</span>
<span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-name-color)">people</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">push</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">newPerson</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">newPerson</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">//return the new object's result</span>
<span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">},</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>
-
addPerson
突变接受 一个name
论点 - 当 a
name
被传递时,程序将创建一个具有匹配name
键的新对象 - 接下来,它将使用该
push
方法将此对象添加到people
数据集中 - 最后,它将新对象的属性返回给客户端
而已!要对其进行测试,请在“操作”窗口中运行此代码:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>#<span style="color:var(--syntax-name-color)">perform</span> <span style="color:var(--syntax-name-color)">a</span> <span style="color:var(--syntax-name-color)">mutation</span> <span style="color:var(--syntax-name-color)">on</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">server</span>
<span style="color:var(--syntax-name-color)">mutation</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">$name</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">String</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">addPerson</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-text-color)">:</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Hussain</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span> #<span style="color:var(--syntax-name-color)">add</span> <span style="color:var(--syntax-name-color)">a</span> <span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-name-color)">person</span> <span style="color:var(--syntax-declaration-color)">with</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">name</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">Hussain</span><span style="color:var(--syntax-string-color)">"</span>
#<span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">execution</span> <span style="color:var(--syntax-name-color)">succeeds</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">its</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">id</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-name-color)">and</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">name` to the user.
id
name
}
}
</span></code></span></span>
让我们验证一下 GraphQL 是否已将新条目添加到数据库中:
<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-name-color)">query</span> <span style="color:var(--syntax-text-color)">{</span>
<span style="color:var(--syntax-name-color)">getAllPeople</span> <span style="color:var(--syntax-text-color)">{</span> #<span style="color:var(--syntax-declaration-color)">get</span> <span style="color:var(--syntax-name-color)">all</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-name-color)">results</span> <span style="color:var(--syntax-name-color)">within</span> <span style="color:var(--syntax-name-color)">the</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">people</span><span style="color:var(--syntax-string-color)">'</span> <span style="color:var(--syntax-name-color)">database</span><span style="color:var(--syntax-text-color)">.</span>
#<span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">only</span> <span style="color:var(--syntax-name-color)">their</span> <span style="color:var(--syntax-name-color)">names</span>
<span style="color:var(--syntax-name-color)">name</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-text-color)">}</span>
</code></span></span>