graphql
by Luis Aguilar
路易斯·阿吉拉尔(Luis Aguilar)
普通英语GraphQL指南 (A Guide to GraphQL in Plain English)
您需要了解的最新流行语正在席卷API开发领域。 (All you need to know about the latest buzzword that’s taking the API development scene by storm.)
TL; DR (TL;DR)
GraphQL is a query language and runtime that we can use to build and expose APIs as a strongly-typed schema instead of hundreds of REST endpoints. Your clients see the schema. They write a query for what they want. They send it over and get back exactly the data they asked for and nothing more.
GraphQL是一种查询语言和运行时,我们可以使用它来构建API并将其显示为强类型架构,而不是数百个REST端点。 您的客户看到架构。 他们编写查询以查找所需内容。 他们将其发送出去,并准确地取回他们所要求的数据,仅此而已。
A schema looks like:
模式如下所示:
So, if a client wants a user with an ID of 2, instead of doing a GET /api/v1/users/2
, they would rather send a query like this:
因此,如果客户端希望一个ID为2的用户,而不是执行GET /api/v1/users/2
,他们宁愿发送如下查询:
… and get a response like this:
……并得到这样的回应:
Why should REST watch its back, and why should you care?
为什么应该休息看它的后面,为什么你要在乎?
-
The schema is strongly-typed. The schema dictates that the
id
parameter must be an integer. If a client sendsuser(id: “2”)
instead, the GraphQL engine will reject the whole query.模式是强类型的。 该模式要求
id
参数必须为整数。 如果客户端改为发送user(id: “2”)
,则GraphQL引擎将拒绝整个查询。 -
Clients pick what they need. See those braces after the query parameters? That’s how our clients tell which fields they want. Fewer fields = leaner and faster responses.
客户选择他们需要的东西。 查询参数后看到那些花括号? 这就是我们的客户告诉他们想要哪些字段的方式。 更少的字段=更精简和更快的响应。
-
It’s fast. Fields not picked won’t be processed, meaning less stress on the server.
它很快。 未选择的字段将不被处理,这将减轻服务器的压力。
-
And most importantly, it’s flexible. If a client needs fewer fields from an endpoint, we don’t create a new endpoint or version our whole API exclusively for that need. They can pick whichever fields they need, and that’s free for us.
最重要的是,它很灵活。 如果客户端从端点需要的字段较少,我们不会专门为此创建新的端点或为整个API版本。 他们可以选择所需的任何字段,这对我们来说是免费的。
And that’s all there is to it, really. No magic is going on. Just a more convenient, flexible, and natural way of building your API.
真的,这就是全部。 没有魔术在继续。 这是构建API的更方便,灵活,自然的方法。
But what is life without those juicy core concepts and sweet, sweet code examples?
但是,如果没有那些多汁的核心概念和甜美,甜美的代码示例,生活将会怎样?
五巨头 (The Big Five)
Before moving onto the actual fun, there are some concepts we need to have in mind, otherwise everything else won’t make any sense.
在开始实际乐趣之前,我们需要牢记一些概念,否则其他所有内容都将毫无意义。
Don’t worry—I’ll keep it short.
不用担心,我会尽量简短。
询问 (Query)
A member of the schema that reads data.
读取数据的架构成员。
突变 (Mutation)
A member of the schema that modifies data (as in create, edit, or delete.)
修改数据(如创建,编辑或删除)的架构成员。
架构图 (Schema)
A single-rooted tree with two primary nodes: one for queries, and another for mutations.
具有两个主节点的单根树:一个用于查询,另一个用于突变。
类型 (Type)
The shape of everything composing the schema. The data returned by a query, the fields of that data, the parameters taken by a mutation, queries, and mutations themselves—everything has a type.
组成架构的所有事物的形状。 查询返回的数据,该数据的字段,突变所采用的参数,查询以及突变本身—每种类型都有。
Types are composed of fields which also have a type.
类型由也具有类型的字段组成。
Both the query
and mutation
initial nodes are of type Query
and Mutation
respectively. These have more fields, users
and user
, and their type can also have more fields! That’s how you structure your API data into a queryable tree.
query
和mutation
初始节点的类型分别为Query
和Mutation
。 这些具有更多字段, users
和user
,并且它们的类型也可以具有更多字段! 这就是您将API数据构造为可查询树的方式。
解析器 (Resolver)
The actual piece that connects your code to your schema. Resolvers are actual functions that resolve the value of a single field in a type. The following is a very, very barebones pseudo example of how it works—don’t mind it too much.
将代码连接到架构的实际部分。 解析器是用于解析类型中单个字段值的实际函数。 以下是其工作方式的非常非常准的伪示例—不必太在意。
Easy, right? Well, that’s it for theory, time for some code!
容易吧? 好了,理论上就是这样,花些时间编写代码!
完全原始且未过度使用的代码示例 (A Totally Original and Not Overused Code Example)
Tired of the classic user model code example? Me neither! Okay, it might be dull and uninteresting, but it serves well to illustrate the previous concepts, so let’s stick to it. By the end, we’ll have an API clients will be able to query for users, roles, and create new users.
厌倦了经典的用户模型代码示例? 我也不! 好的,它可能很枯燥和无趣,但是可以很好地说明以前的概念,所以让我们坚持下去。 到最后,我们将拥有一个API客户端,这些客户端将能够查询用户,角色并创建新用户。
1.创建服务器 (1. Create a Server)
As already mentioned, GraphQL is a language, and a runtime—we still have to put it somewhere. For this example, it will live in an Express server.
如前所述,GraphQL是一种语言, 也是一种运行时,我们仍然必须将其放在某个地方。 对于此示例,它将驻留在Express服务器中。
So let’s get started:
因此,让我们开始吧:
- Create a new folder.
新建一个文件夹。
-
Open a terminal and
cd
to your folder.打开一个终端并
cd
到您的文件夹。 -
Run
npm init && touch server.js
运行
npm init && touch server.js
-
Run
npm i express --save
to, well, install ExpressJS.运行
npm i express --save
到ExpressJS。 -
Throw this into
server.js
:扔到
server.js
:
-
Run the server with
node server.js
使用
node server.js
运行服务器
And so we have a home for our GraphQL API.
因此,我们有了GraphQL API的家。
2.添加一小撮GraphQL (2. Add a Pinch of GraphQL)
As simple as:
简单如:
-
Run
npm i graphql graphql-express --save
运行
npm i graphql graphql-express --save
-
Edit
server.js
like this:像这样编辑
server.js
:
And this is why it was essential to review the concepts before moving onto the code. This simple Hello World app already has a lot going on, but we can at least get an idea.
这就是为什么在移入代码之前必须先复习这些概念的原因。 这个简单的Hello World应用程序已经进行了很多工作,但是我们至少可以了解一下。
Don’t worry, here’s the annotated version:
别担心,这是带注释的版本:
Wait, are we hardcoding our schema using a huge magic string? Don’t panic— we’ll get to that later.
等等,我们是否使用巨大的魔术字符串对模式进行硬编码? 不要惊慌,我们稍后再讨论。
Okay, time to fire up Postman and send some queries to our GraphQL API!
好的,是时候启动Postman并将一些查询发送到我们的GraphQL API了!
Heh, just kidding…
嘿,开玩笑…
At line 46
we enabled GraphiQL (pronounced “graphical,”) a built-in fully-featured IDE for writing queries. Now, close Postman and go to localhost:4000/graphql
in your browser of preference.
在第46
行,我们启用了GraphiQL(发音为“ graphical” ),这是一个内置的功能齐全的IDE,用于编写查询。 现在,关闭Postman并在您偏好的浏览器中转到localhost:4000/graphql
。
What can you do with this? Well, here are some things you can try:
你能做什么呢? 好了,您可以尝试以下操作:
-
View schema. To the right, select the
Query
root type to see its fields, return types, documentation, etc.查看架构。 在右侧,选择
Query
根类型以查看其字段,返回类型,文档等。 -
Write queries. To the left, type the following query, and notice how the editor shows autocompletion and documentation as you go:
编写查询。 在左侧,键入以下查询,并注意编辑器在显示过程中如何显示自动完成和文档:
-
Test queries. If your query is valid, hit that play button at the top and see the results in the middle pane.
测试查询。 如果查询有效,请点击顶部的播放按钮,然后在中间窗格中查看结果。
But what about clients? They can use GraphiQL (or a similar tool—there are tons) to build and test their queries. Then send them over using a GraphQL client like Apollo Boost—as easy as copying and pasting!
但是客户呢? 他们可以使用Graph i QL(或类似的工具-有很多)来构建和测试他们的查询。 然后使用像Apollo Boost这样的GraphQL客户端将它们发送过来,就像复制和粘贴一样简单!
3.添加查询以列出用户 (3. Add a Query to List Users)
All right, Hello World is fine and all, but we want to do more than greeting people. Let’s add a new User
type, and replace hello
with users
which will return all users from a dummy repository.
好的,Hello World很好,但是,我们要做的不仅仅是问候别人。 让我们添加一个新的User
类型,然后用users
替换hello
,这将返回虚拟存储库中的所有用户。
-
Edit
server.js
like this:像这样编辑
server.js
:
-
Grab the
user-repository.js
file from here and put it in your local directory.从此处获取
user-repository.js
文件,并将其放在您的本地目录中。 -
Restart your server and refresh the GraphiQL editor.
重新启动服务器并刷新Graph i QL编辑器。
-
In your query, replace
hello
forusers { id, login }
and hit play.在您的查询中,为
users { id, login }
替换hello
users { id, login }
然后点击播放。 -
Profit.
利润。
Annotated:
注释:
4.添加查询以按ID获取单个用户 (4. Add a Query to Get a Single User By ID)
By now, you might be asking: if queries are also fields of a type, why not call them fields? What makes them different?
现在,您可能会问:如果查询也是一种类型的字段,为什么不将它们称为字段? 是什么使它们与众不同?
Queries can take parameters and use a resolver.
查询可以采用参数并使用解析器。
The easiest way to see it is to compare it to OOP classes. While classes have fields and functions, GraphQL types have fields and queries.
最简单的查看方法是将其与OOP类进行比较。 虽然类具有字段和函数,但是GraphQL类型具有字段和查询。
-
Edit
server.js
with:使用以下命令编辑
server.js
:
Again, no magic.
再次,没有魔术。
We’re saying the user
query takes an id
parameter, and that’s what its resolver function will take. Oh, also notice the !
sign meaning the parameter is required—GraphQL will make sure it is provided.
我们说的是user
查询使用id
参数,这就是它的解析器函数所采用的参数。 呵呵,还注意了!
符号表示该参数是必需的-GraphQL将确保已提供该参数。
5.用手动定义替换Schema Builder (5. Replace Schema Builder with Manual Definitions)
Remember how we called out that huge magic string we used to define our schema? Well, it’s time to fix that.
还记得我们如何调出用来定义架构的巨大魔术字符串吗? 好了,是时候解决这个问题了。
Okay, in a real-world app, you would put your schema in separate *.graphql
files. Then you can add syntax highlighting and code completion plugins to your code editor. However, manual definitions offers a better integration with the rest of our code. Check out this article for more info.
好的,在真实世界的应用程序中,您可以将架构放在单独的*.graphql
文件中。 然后,您可以将语法高亮和代码完成插件添加到代码编辑器中。 但是,手动定义可以与我们的其余代码更好地集成。 查看这篇文章以获取更多信息。
For this step, we’ll use the specialized classes and helpers provided by GraphQL:
在此步骤中,我们将使用GraphQL提供的专用类和帮助器:
Done? Okay, now annotated:
做完了吗 好的,现在注释:
This way we can put our type definitions in separate files to better organize our server code!
这样,我们可以将类型定义放在单独的文件中,以更好地组织服务器代码!
As pointed out in the example, in this notation, the resolver function takes the following parameters:
如示例中指出的那样,在这种表示法中,resolver函数采用以下参数:
-
root
—the resolved parent object, in this case the user.root
–解析的父对象,在这种情况下,用户。 -
args
—arguments passed by the query.args
–参数被查询过。 -
context
,info
—out of the scope of this guide.context
,info
-在本指南的范围之外。
6.添加用于获取用户角色的子查询 (6. Add a Sub-query for Fetching User Roles)
So far, we’ve learned to define basic queries. Time to turn it up a notch! Let’s add a new field to the User
type for its assigned roles. In a traditional architecture, we’d be tempted to create a new query like userRoles(userId: Int!): Role
and call it a day. But that’s not how things work in GraphQL!
到目前为止,我们已经学会了定义基本查询。 是时候提高它了! 让我们在“ User
类型”中为其分配的角色添加一个新字段。 在传统的体系结构中,我们很想创建一个新的查询,例如userRoles(userId: Int!): Role
并称之为一天。 但这不是GraphQL的工作原理!
We have to think in graphs.
我们必须考虑图表 。
In the language of graphs, to get the roles of a user we’d send a query like this:
用图的语言,要获得用户的角色,我们将发送如下查询:
… and get a JSON result like this:
…并获得如下的JSON结果:
Makes sense, right? Let’s go ahead and modify the schema.
有道理吧? 让我们继续修改模式。
-
Edit
server.js
with:使用以下命令编辑
server.js
:
There—we can fetch user roles now. Notice how we used the User
instance passed as the first parameter to the resolver to get the ID from the parent resolved user.
在那里-我们现在可以获取用户角色。 请注意,我们如何使用作为第一个参数传递给解析器的User
实例从父解析用户获取ID。
The advantage of subqueries? GraphQL won’t resolve the roles
field unless it’s selected in the query.
子查询的优势? 除非在查询中选择GraphQL,否则GraphQL不会解析roles
字段。
Did you spot the pitfall with the last bit of code?
您是否发现了最后一部分代码的隐患?
If we query 100 users and their roles, the roles
resolver function will execute a hundred times. Then, let’s say each user has 10 roles and each role has a sub-query field. That query will execute 100 * 10 times.
如果我们查询100个用户及其角色,则roles
解析器功能将执行一百次。 然后,假设每个用户有10个角色,每个角色都有一个子查询字段。 该查询将执行100 * 10次。
This is called The N + 1 Problem.
这称为N + 1问题 。
Finding out how to fix that is your homework! But it’s dangerous to go alone, so take this:
找出解决方法,这是您的作业! 但是独自一人走是危险的,因此请采取以下措施:
Avoiding n+1 requests in GraphQL, including within subscriptionsNote: this article will not make much sense unless you know the basics of GraphQL, an awesome technology we use at…medium.com
避免在GraphQL中出现n + 1个请求,包括在订阅中。 注意:除非您了解GraphQL的基础知识,否则本文将没有多大意义,GraphQL是我们在… medium.com上使用的一种很棒的技术
7.添加一个变体来创建一个新用户 (7. Add a Mutation to Create a New User)
As mentioned before, mutations are how we change data in our schema. If we want to create, edit, or delete a user account, we’ll need a mutation for that.
如前所述, 变异是我们更改架构数据的方式。 如果我们要创建,编辑或删除用户帐户,则需要对其进行更改。
Mutations are defined almost exactly the same as a query, and often return the affected data. So the only difference between them is merely logical?
定义的突变与查询几乎完全相同,并且通常返回受影响的数据。 因此,它们之间的唯一区别仅仅是合乎逻辑的吗?
Exactly.
究竟。
As mentioned before, queries can also take parameters. They only return data.
如前所述,查询也可以采用参数。 它们仅返回数据。
-
Edit
server.js
with:使用以下命令编辑
server.js
:
-
Send the following query from GraphiQL:
从Graph i QL发送以下查询:
-
Profit.
利润。
结论 (Conclusion)
So, hopefully, the basics of GraphQL are clear: setting up a server, creating a schema (in plain and complex notation) with types, queries, and mutations. I used quite a basic example. Hopefully it served well for illustrating every concept unobtrusively.
因此,希望GraphQL的基本知识很清楚:设置服务器,使用类型,查询和变异创建模式(以简单和复杂的符号表示)。 我用了一个很基本的例子。 希望它能很好地说明每个概念。
From this point onwards, it’s up to you to expand the example with more stuff. Or you can create a completely new codebase for another use case.
从现在开始,由您自己来扩展更多内容的示例。 或者,您可以为另一个用例创建一个全新的代码库。
To get you going, here are a few things you can try out:
为了助您一臂之力,您可以尝试以下一些操作:
- Solving the N+1 problem by implementing data loaders.
通过实现数据加载器解决N + 1问题。
- Create mutations for validating user credentials, managing user roles, and more.
创建用于验证用户凭据,管理用户角色等的变体。
- Add an actual database to feed your resolvers (MySQL, SQLite, etc.)
添加实际的数据库以供解析器使用(MySQL,SQLite等)
- Use an authentication backend like OAuth to validate users.
使用OAuth之类的身份验证后端来验证用户。
- Create a simple client app that uses the Apollo Boost client to connect to your server.
创建一个使用Apollo Boost客户端连接到服务器的简单客户端应用程序。
- Rebuild the example with TypeScript.
用TypeScript重建示例。
Possibilities are endless!
可能性是无止境的!
获取源代码 (Get the Source Code)
The entire example is hosted in GitHub. Browse through the tags to see a gradual progression of the code.
整个示例托管在GitHub中。 浏览标签以查看代码的逐步进展。
ldiego08/workshops-graphqlGitHub is where people build software. More than 28 million people use GitHub to discover, fork, and contribute to over…github.com
ldiego08 / workshops-graphql 人们可以在GitHub上构建软件。 超过2千8百万的人使用GitHub来发现,发掘和贡献超过 github.com
Got questions, comments, or anything you’d like to share? Find me on Twitter as @ldiego08. Also, don’t forget to ?, share, and follow if this post was helpful!
有问题,评论或您想分享的任何内容? 在Twitter上以@ ldiego08找到我。 此外,如果这篇文章对您有帮助,请不要忘记分享,关注!
Luis Aguilar (@ldiego08) | TwitterSan José, Costa Rica — Writer of sci-fi, software dev @skillshare. twitter.com
路易斯·阿吉拉(Luis Aguilar)(@ ldiego08)| Twitter 哥斯达黎加的SanJosé,科幻作家,软件开发人员@skillshare。 twitter.com
翻译自: https://www.freecodecamp.org/news/a-beginners-guide-to-graphql-60e43b0a41f5/
graphql