graphql

有兴趣学习JavaScript吗? 在jshandbook.com上获取我的免费电子书

GraphQL是API( 应用程序编程接口 )中的新领域。

它是API的查询语言,是用于执行查询的一组服务器端运行时(以各种后端语言实现)。

它与特定技术无关,但是您可以使用任何语言来实现它。

它是一种直接与REST ( 代表性状态转移 )API 竞争的方法,就像REST首先与SOAP竞争一样。

GraphQL是在Facebook上开发的 ,就像最近震动世界的许多技术一样,例如React和React Native,它于2015年公开发布 -尽管Facebook在内部使用了几年。

许多大公司都在Facebook旁边采用GraphQL,包括GitHub,Pinterest,Twitter,Sky,《纽约时报》,Shopify,Yelp等数千种。

GraphQL原理

GraphQL公开单个端点 。

您使用特殊的查询语言语法将查询发送到该端点 。 该查询只是一个字符串 。

服务器通过提供JSON对象来响应查询。

让我们看看这种查询的第一个例子。 此查询获取id=1的人的名字:

GET /graphql?query={ person(id: "1") { name } }

或简单地

{ person(id: "1") { name } }

我们将返回此JSON响应:

{ "name": "Tony" }

让我们增加一点复杂性:通过从address对象中提取人的名字以及人所居住的城市。 我们不在乎地址的其他详细信息,并且服务器不会将其退还给我们。

GET /graphql?query={ person(id: "1") { name, address { city } } }

要么

{
person(id: "1") {
name
address {
city
}
}
}
{
"name": "Tony",
"address": {
"city": "York"
}
}

如您所见,我们获取的数据基本上与我们发送的请求相同,并填充了值。

GraphQL与REST

由于REST是构建API的一种流行方法,或者可以说是通用方法,因此可以假设您很熟悉REST,因此,让我们看看GraphQL和REST之间的区别。

休息是一个概念

REST是事实上的体系结构标准,但实际上它没有规范和大量的非正式定义。 GraphQL有一个规范草案,它是一种查询语言,而不是一种体系结构,围绕它构建了一套定义良好的工具(以及蓬勃发展的生态系统)。

REST建立在现有体系结构(在最常见的场景是HTTP)的基础上,而GraphQL正在构建自己的约定集。 这可能不是优势点,因为REST通过在HTTP层上进行缓存而免费受益。

单一端点

GraphQL只有一个端点,您可以在其中发送所有查询。 使用REST方法,您可以创建多个端点并使用HTTP 动词来区分读取动作(GET)和写入动作(POST,PUT,DELETE)。 GraphQL不使用HTTP动词来确定请求类型。

根据您的需求量身定制

使用REST,通常不能选择服务器返回给您的内容,除非服务器使用稀疏字段集实现部分响应,并且客户端使用该功能。 API维护者无法强制执行此类过滤。

API通常会向您返回比您需要的信息更多的信息,除非您也控制API服务器,并且针对每个不同的请求量身定制响应。

使用GraphQL,您可以显式地仅请求所需的信息,而不必从完整的响应默认值中“退出”,但是必须选择所需的字段。

这有助于节省服务器上的资源,因为您最有可能需要较少的处理,并且还可以节省网络,因为要传输的有效负载较小。

GraphQL使其易于监视字段使用情况

使用REST,除非强制使用稀疏字段集,否则无法确定客户端是否使用了字段,因此,在进行重构或弃用时,无法确定实际使用情况。

GraphQL使得可以跟踪客户端使用哪些字段。

访问嵌套的数据资源

GraphQL允许生成更少的网络调用。

让我们举个例子:您需要访问一个人的朋友的名字。 如果您的REST API公开了/person端点,该端点返回带有好友列表的person对象,那么通常通常首先通过执行GET /person/1获取该人物信息,该列表包含其好友ID的列表。

除非一个人的朋友列表中已经包含该朋友的名字,否则您需要与100个朋友向/person端点进行101个HTTP请求,这将花费大量时间,并且也是一项资源密集型操作。

使用GraphQL,您只需要一个请求,即可请求一个人的朋友的名字。

种类

REST API基于无法提供类型控制的JSON。 GraphQL具有类型系统 。

哪一个更好?

世界各地的组织都在质疑他们的API技术选择,他们试图找出从REST迁移到GraphQL是否最适合他们的需求。

当您需要公开复杂的数据表示形式,或者客户端可能只需要数据的一个子集,或者客户端定期执行嵌套查询以获取所需的数据时,GraphQL是一个完美的选择。

与编程语言一样,没有一个赢家,这完全取决于您的需求。

GraphQL查询

在本文中,您将学习如何构成GraphQL查询。

我将介绍的概念是

  • 字段和参数
  • 别名
  • 碎片

字段和参数

进行以下简单的GraphQL查询:

{
person(id: "1") {
name
}
}

在此查询中,您将看到2个字段和1个参数。

现场person返回其中包含另一个字段String的Object 。

该参数允许我们指定要引用的人。 我们传递一个id ,但我们也可以传递一个name参数,如果与我们交谈的API可以选择按名称查找一个人。

参数不限于任何特定字段,我们可以person列出一个friends字段,并可以使用limit参数来指定我们希望API返回多少个参数:

{
person(id: "1") {
name
friends(limit: 100)
}
}

别名

您可以要求API返回具有不同名称的字段,例如:

{
owner: person(id: "1") {
fullname: name
}
}

将返回

{
"data": {
"owner": {
"fullname": "Tony"
}
}
}

如果您需要在同一查询中两次引用相同的端点 ,则此功能除了为您的客户端代码创建更多临时命名之外,还可以使查询正常工作:

{
owner: person(id: "1") {
fullname: name
}
first_employee: person(id: "2") {
fullname: name
}
}

碎片

在上面的查询中,我们复制了人员结构。 片段使我们可以一次指定结构(在许多字段中非常有用):

{
owner: person(id: "1") {
...personFields
}
first_employee: person(id: "2") {
...personFields
}
}
fragment personFields on person {
fullname: name
}

GraphQL变量

更复杂的GraphQL查询需要使用变量 ,这是一种动态指定在查询内部使用的值的方法。

在这种情况下,我们将人员ID作为字符串添加到查询中:

{
owner: person(id: "1") {
fullname: name
}
}

id很可能会在我们的程序中动态更改,因此我们需要一种传递它的方法,而不是使用字符串插值 。

使用变量,可以将相同的查询写为

query GetOwner($id: String) {
owner: person(id: $id) {
fullname: name
}
}
{
"id": "1"
}

在此代码段中,我们为查询分配了GetOwner名称。 在拥有匿名函数之前,请将其视为命名函数。 当您的应用程序中有很多查询时,命名查询很有用。

具有变量的查询定义看起来像函数定义,并且以相同的方式工作。

使变量为必需

附加一个! 类型:

query GetOwner($id: String!)

而不是$id: String将使$ id变量成为必需。

指定变量的默认值

您可以使用以下语法指定默认值:

query GetOwner($id: String = "1")

GraphQL指令

指令允许您在变量为true或false时包含或排除字段。

query GetPerson($id: String, $getAddress: Boolean) {
person(id: $id) {
fullname: name,
address: @include(if: $getAddress) {
city
street
country
}
}
}
{
"id": "1",
"getAddress": false
}

在这种情况下,如果我们传递的getAddress变量为true,那么我们还将获取地址字段,否则返回。

我们有2个指令可用: include ,我们刚刚看过(如果为true则包含),以及skip ,这是相反的(如果为true则跳过)

@include(如果:布尔值)

query GetPerson($id: String, $getAddress: Boolean) {
person(id: $id) {
fullname: name,
address: @include(if: $getAddress) {
city
street
country
}
}
}
{
"id": "1",
"getAddress": false
}

@skip(如果是布尔值)

query GetPerson($id: String, $excludeAddress: Boolean) {
person(id: $id) {
fullname: name,
address: @skip(if: $excludeAddress) {
city
street
country
}
}
}
{
"id": "1",
"excludeAddress": false
}
有兴趣学习JavaScript吗? 在jshandbook.com上获取我的免费电子书

翻译自: https://hackernoon.com/an-introduction-to-graphql-2c3f7d8fb4e0

graphql

更多推荐