用户您好!请先登录!

GraphQL那点事

GraphQL那点事

GraphQL,代替restful接口的新一代API查询语言!

还在用restful接口?你out了!如今接口开发都这么做

1. 基本介绍

1.1 简介

GraphQL是一种新的API标准,它提供了一种比REST更有效、更强大和更灵活的替代方案。它是由Facebook开发并开源的,现在由来自世界各地的公司和个人组成的大型社区维护。

API已经成为软件基础结构中无处不在的组件。简而言之,API定义了客户客户端如何从服务器加载数据。

在其核心部分,GraphQL支持声明式数据获取,客户端可以在其中准确地指定需要从API获取哪些数据。与返回固定数据结构的多个端点(multiple endpoints)不同,GraphQL服务器只公开单个端点(a single endpoint),并使用客户机请求的准确数据进行响应。

1.2 GraphQL:一种API查询语言

现在的大多数应用程序都需要从服务器获取存储在数据库中的数据。API的职责是为存储的数据提供符合应用程序需求的接口。

GraphQL经常与数据库技术混淆。这是一种误解,GraphQL是API(而不是数据库)的查询语言。从这个意义上说,它与数据库无关,可以在使用API的任何上下文中有效地使用。

1.3 一个可以代替REST的高效选择

想要了解更多为什么使用GraphQL的主要原因请复制以下链接到浏览器打开:https://www.prisma.io/blog/top-5-reasons-to-use-graphql-b60cfa683511

REST是公开服务器数据的一种流行方法。当REST的概念被开发时,客户端应用程序相对简单,开发速度远不及今天。因此REST非常适合于许多应用程序。然而,API环境在过去几年中发生了根本的变化。特别是,有三个因素一直在挑战API的设计方式:

  1. 手机等移动终端使用的增加产生了对高效数据加载的需求Facebook开发GraphQL的最初原因是移动应用的增加、低功率设备和松散的网络。GraphQL最小化了需要通过网络传输的数据量,从而极大地改进了在这些条件下运行的应用程序。
  2. 各种不同的前端框架和平台运行客户端应用程序的前端框架和平台的异构环境使得构建和维护一个满足所有需求的API变得非常困难。使用GraphQL,每个客户端都可以准确地访问所需的数据。
  3. 快速开发&对快速特性开发的期望持续部署已经成为许多公司的标准,快速的迭代和频繁的产品更新是必不可少的。使用REST API,服务器公开数据的方式通常需要修改,以满足客户端的特定需求和设计更改。这阻碍了快速开发实践和产品迭代。

1.4 历史,背景和采用

1.4.1 GraphQL 不仅仅 适用于React开发人员

2012年,Facebook开始在其原生移动应用程序中使用GraphQL。不过,有趣的是,GraphQL主要是在web技术上下文中使用的,在本地移动领域只获得很少的关注。

Facebook第一次公开谈论GraphQL是在React.js 会议 2015上,会议不久后Facebook宣布他们开放GraphQL源代码的计划。因为Facebook总是在使用React的情况下谈论GraphQL,而非React开发人员需要花一段时间才会明白:GraphQL绝不是一种仅限于与React一起使用的技术。

1.4.2 快速成长的社区

事实上,GraphQL是一种技术,可以在客户端与API通信的任何地方使用。有趣的是,Netflix和Coursera等其他公司也在研究类似的想法,以提高API交互的效率。Coursera设想了一种类似的技术,让客户端明确自己的数据需求,Netflix甚至开放了名为Falcor的解决方案的源代码。在GraphQL开源之后,Coursera完全取消了自己的努力,加入了GraphQL的行列。

今天,GraphQL被许多不同的公司用于生产中,如GitHub、Twitter、Yelp和Shopify——仅举几个例子。

还在用restful接口?你out了!如今接口开发都这么做

使用GraphQL的公司

尽管GraphQL是如此年轻的技术,但它已经被广泛采用。了解还有哪些公司在生产中使用GraphQL。

问题:下面哪个描述是正确的?

  • [ ] GraphQL是一种数据库技术
  • [ ] GraphQL只能与SQL一起使用
  • [✔] GraphQL是由Facebook发明的
  • [ ] GraphQL是由Netflix和Coursera开发的

2. GraphQL是更好的REST

在过去的十年中 REST 已经成为设计web api的标准(尽管还很模糊)。它提供了一些很棒的想法,比如无状态服务器和对资源的结构化访问。然而,REST API已经被证明过于僵化,无法跟上访问它们的客户端快速变化的需求。

GraphQL的开发是为了满足对更大灵活性和效率的需求!它解决了开发人员在与REST API交互时遇到的许多缺点和低效。

为了说明REST和GraphQL在从API获取数据时的主要区别,让我们考虑一个简单的示例场景:在博客应用程序中,应用程序需要显示特定用户的文章标题。同一屏幕还显示该用户最后3个关注者的名称。如何使用REST和GraphQL解决这种情况?

想要了解更多关于开发人员为什么喜欢GraphQL的信息以下链接到浏览器打开:

https://www.prisma.io/blog/top-5-reasons-to-use-graphql-b60cfa683511

2.1 获取数据的方式:REST vs GraphQL

使用REST API,您通常会通过访问多个端点来收集数据。在本例中,这些端点可以是 /users/<id> 端点来获取初始用户数据。其次,可能存在一个 /users/<id>/posts 端点,该端点返回用户的所有文章。第三个端点是 /users/<id>/follower ,它返回每个用户的follower列表。

还在用restful接口?你out了!如今接口开发都这么做

使用REST,你必须向不同的端点发出三个请求来获取所需的数据。此外你还可能获取到端点返回的你并不需要的额外信息。

而在GraphQL中,只需向GraphQL服务器发送一个包含具体数据需求的查询。然后,服务器会返回一个满足这些需求的JSON对象。

还在用restful接口?你out了!如今接口开发都这么做

使用GraphQL,客户端可以在查询中准确地指定所需的数据。请注意,服务器响应的结构完全遵循查询中定义的嵌套结构。

2.2 不再是多取(Overfetching)和少取(Underfetching)数据

REST最常见的问题之一是获取过多和不足。这是因为客户端下载数据的唯一方法是访问返回固定数据结构的端点。很难将API设计成能够为客户提供准确数据需求的方式。

“Think in graphs, not endpoints.”——这是GraphQL的共同发明人Lee Byron从4年的GraphQL中总结的经验教训。

http://www.graphql.com/articles/4-years-of-graphql-lee-byron

2.2.1 Overfetching:取到多余的数据

Overfetching意味着客户端取到的信息比应用程序实际需要的要多。例如,假设一个界面只需要显示包含用户姓名的用户列表,在REST API中,客户端通常会请求 /users 端点并接收一个包含用户数据的JSON数组。然而,服务器响应可能会返回包含更多关于用户的信息,例如他们的生日或地址——这些信息对于客户端是无用的,因为它只需要显示用户的姓名。

2.2.2 Underfetching:获取数据不足和 n+1 问题

另一个问题是获取数据不足和 n + 1 个请求的问题。取不到通常意味着特定端点不能提供足够的所需信息。客户端必须发出额外的请求来获取它需要的所有东西。这可能会升级到这样一种情况:客户端首先需要下载元素列表,然后需要为每个元素发出一个额外的请求来获取所需的数据。

例如,考虑该应用程序还需要为每个用户显示最后三个关注者。这个API提供了额外的端点 /users/<user-id>/follower。为了能够显示所需的信息,应用程序必须向 /users 端点发出一个请求,然后为每个用户命中 /users/<user-id>/follower 端点。

2.3 前端的快速产品迭代

REST API的一个常见模式是根据应用程序内部的视图来构造端点。这很方便,因为它允许客户端通过访问相应的端点来获得特定视图所需的所有信息。

这种方法的主要缺点是不允许在前端进行快速迭代。对UI所做的每一次更改都有一个很高的风险,即现在所需的数据比以前更多(或更少)。因此,后端也需要根据新的数据需求进行调整。这降低了生产效率,并明显降低了将用户反馈整合到产品中的能力。

而GraphQL解决了这个问题。由于GraphQL的灵活性,客户端上的更改无需在服务器上做任何额外的工作。由于客户端可以指定准确的数据需求,所以当前端的设计和数据需求发生变化时,不需要后端工程师进行调整。

2.4 后端的深刻分析

GraphQL允许你对后端请求的数据有细粒度的了解。由于每个客户端准确地指定了它感兴趣的信息,因此有可能深入了解可用数据是如何被使用的。这就有了更多好处,例如这可以帮助API的演变和废弃不再由任何客户端请求使用的特定字段等。

使用GraphQL,你还可以对服务器处理的请求进行低级性能监视。GraphQL使用解析器函数的概念来收集客户端请求的数据。对这些解析器的性能进行检测和测量,可以对系统中的瓶颈提供至关重要的见解。

2.5 模式(Schema )和类型(Type)系统的好处

GraphQL使用强类型系统来定义API的功能。API中公开的所有类型都是使用GraphQL模式定义语言(SDL)在模式中编写的。此模式充当客户端和服务器之间的契约,用于定义客户端如何访问数据。

一旦定义了模式,从事前端和后端工作的团队就可以在没有进一步通信的情况下完成工作,因为他们都知道通过网络发送的数据的确切结构。

前端团队可以通过模拟(Mock)所需的数据结构轻松地测试他们的应用程序。一旦服务器准备就绪,就可以通过切换开关,让客户端应用程序从实际API加载数据。

问题:GraphQL模式和强类型系统的好处是什么?

  • [ ] 它们与Javascript类型系统配合得很好
  • [✔] 一旦定义了模式,前端和后端团队就可以彼此独立地工作
  • [ ] 它解决了 n+1 请求问题
  • [ ] 偏题:GraphQL没有类型系统

3. 核心概念

在本章中,您将了解GraphQL的一些基本语言结构。这包括对定义类型以及发送查询(queries)和更新(mutations)的语法的初步了解。我们还为你准备了一个基于graphql-up(https://www.npmjs.com/package/graphql-up)的沙箱环境,你可以使用它来试验您所学的知识。

3.1 模式定义语言(SDL)

GraphQL有自己的类型系统,用于定义API的模式。编写模式的语法称为模式定义语言(Schema Definition Language, SDL)。

下面是我们如何使用SDL定义一个简单类型Person的例子:

type Person {

name: String!

age: Int!

}

这个类型有两个字段,它们分别是 name 和 age ,类型是 String 和 Int 。类型后面的 ! 此字段是必须的。

还可以表示类型之间的关联关系。在博客应用程序的例子中,一篇文章 Post 可以对应一个作者Person,可以形成多对一的关联关系:

type Post {

title: String!

author: Person!

}

反之,一个人可能会发表多篇文章,这种一对多的关联关系在Person类型上的表示如下:

type Person {

name: String!

age: Int!

posts: [Post!]!

}

注意,我们只是在 Person 和 Post 之间创建了一对多的关系,因为 Person 上的 posts 字段实际上是一个 Post 数组。

3.2 使用查询获取数据

在使用REST API时,数据是从特定端点加载的。每个端点返回的信息都有一个明确定义的结构。这意味着客户端的数据需求有效地编码在它所连接的URL中。

GraphQL中采用的方法完全不同。GraphQL API通常只公开一个端点,而不是返回固定数据结构的多个端点。这是因为返回的数据结构不是固定的。相反,它是完全灵活的,可以让客户端决定实际需要什么数据。

这意味着客户端需要向服务器发送更多的信息来表达其数据需求——这些信息称为查询。

3.2.1 基本查询

让我们看一个客户端可以发送到服务器的查询示例:

{

allPersons {

name

}

}

此查询中的 allPersons 字段称为查询的根字段。根字段后面的所有内容都称为查询的有效负载(payload)。在该查询的有效负载中指定的唯一字段是 name 

Person:

id | name | age

cjs1lw3sh16vd0154o0q0kcav | Johnny | 23

cjs1lw3uy16vj0154ykmo54bs | Sarah | 20

cjs1lw3w216vn0154ef6q00i9 | Alice | 20

这个查询将返回当前存储在数据库中的所有人员的列表。下面是上述示例的返回数据:

{

“allPersons”: [

{ “name”: “Johnny” },

{ “name”: “Sarah” },

{ “name”: “Alice” }

]

}

注意,在响应结果中每个 Person 只有 name 字段,但是服务器并没有返回 age 字段。这正是因为 name 是查询中指定的唯一字段。

如果客户端还需要用户的年龄,只需稍微调整查询,在查询声明中包含新字段:

{

allPersons {

name

age

}

}

则服务器将会返回结果:

{

“data”: {

“allPersons”: [

{

“name”: “Johnny”,

“age”: 23

},

{

“name”: “Sarah”,

“age”: 20

},

{

“name”: “Alice”,

“age”: 20

}

]

}

}

GraphQL的主要优势之一是允许自然地查询嵌套信息。例如,如果你想加载一个人写的所有文章,你可以简单地按照你的类型结构来请求这些信息:

{

allPersons {

name

age

posts {

title

}

}

}

然后服务器将会返回如下数据:

{

“data”: {

“allPersons”: [

{

“name”: “Johnny”,

“age”: 23,

“posts”: [

{

“title”: “GraphQL is awesome”

},

{

“title”: “Relay is a powerful GraphQL Client”

}

]

},

{

“name”: “Sarah”,

“age”: 20,

“posts”: [

{

“title”: “How to get started with React & GraphQL”

}

]

},

{

“name”: “Alice”,

“age”: 20,

“posts”: []

}

]

}

}

3.2.2 查询参数

在GraphQL中,如果在模式(schema)中指定了参数(arguments),则每个字段可以有零个或多个参数。例如,allPersons字段的最后一个参数只能返回特定数量的人员。下面是相应的查询:

{

allPersons(last: 2) {

name

}

}

返回结果:

{

“data”: {

“allPersons”: [

{

“name”: “Sarah”

},

{

“name”: “Alice”

}

]

}

}

行走的code
行走的code

要发表评论,您必须先登录