GraphQL+Relay初探

GraphQL简介


GraphQL是Facebook开源的一套用于API的查询语言和runtime,其比较明显的特色在于用一次请求拿到所有想要的数据,并且返回的查询结果与想要查询的格式一致。同时也强调了强类型,减少冗余。

Query/Mutation

(后文大部分例子皆来自/魔改自官方文档)
拿一个如下的简单的query来分析,这里的hero,name或者friends叫做field,field会返回type中定义的类型。

  • field能通过例如hero(name: "R2-D2")这样的方式来添加参数
  • 多个同级同类型的field能通过例如empireHero: hero 来指定别名
  • 多个filed要查询相同类型的数据时,可以用碎片(fragments)来复用相同的查询条件
  • 当遇到多个查询需要带上不同的参数时,可以使用变量
  • 可以用指令(directive)去动态的改变query的结构和形状,如@include(if: Boolean) @skip(if: Boolean)

    1
    2
    3
    4
    5
    6
    7
    8
    query Hero($episode: Episode, $withFriends: Boolean!) {
    hero(episode: $episode) {
    name
    friends @include(if: $withFriends) {
    name
    }
    }
    }
  • GraphQL不只是提供了获得数据的方式,也提供了Mutation去修改服务端的数据

    1
    2
    3
    4
    5
    6
    mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
    createReview(episode: $ep, review: $review) {
    stars
    commentary
    }
    }
  • GraphQL的schemas能定义接口和结合(union)的type,因此当query中的field在schema中对应这些type时,你需要内联碎片(inline fragments)去获取混合(concrete)type之下的数据。

  • 当不知道服务器返回的type时,可以用meta field去代替,即在field前加上__
    例如 我们要查询带有’an’的数据,同时也不知道返回的数据的type,如果这个返回的数据的type是Droid,则会同时返回primaryFunction,如果为Human类型,则会返回height。此外返回结果里的__typename就会是这个查询结果的type的名字了(此例中可能为Human、Droid或者Starship)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    {
    search(text: "an") {
    __typename
    ... on Human {
    height
    }
    ... on Droid {
    primaryFunction
    }
    ... on Starship {
    name
    }
    }
    }

Types/Schemas

上一节中提到了许多次type,type即我们想要查询的field的类型,用于描述我们想要的数据。属于schema中最基础的一类

每一个GarphQL Service定义了一系列的type用于完全描述一系列可能会被查询到的数据。当query来的时候,GraphQL Service会根据schema去验证并执行。

GraphQL Service可以用任何语言去编写。同时还有一种叫做”GraphQL schema language”的语言用于描述schema。

一个简单的定义名为Character的type的例子

  • name,appearsIn和length为该type的field
  • field的type后面的!表示该field不可为null
  • appearsIn: [Episode]表示对应这个appearsIn对应的是一个Episode类型的数据的数组
  • schema中的参数必须有名字,等号前的为参数的type,后面的为默认值
  • 一些基本的type:Int Float String Boolean ID

    1
    2
    3
    4
    5
    type Character {
    name: String!
    appearsIn: [Episode]!
    height(unit: LengthUnit = METER): Float
    }
  • 纯量(scalar):经常作为query的叶结点,例如最前面的query例子里的name。可以用scalar去声明一个纯量 scalar Date

  • 枚举(enum):枚举是一种特殊的纯量,他被限制为一个特定允许值的集合。这个特性可以拿来做验证或者利用一个有限集合的值来在type系统之间传送,可以用如下方式声明,Episode一定会为NEWHOPE、EMPIRE、和JEDI其中之一

    1
    2
    3
    4
    5
    enum Episode {
    NEWHOPE
    EMPIRE
    JEDI
    }
  • 接口(interface):像许多强类型语言一样,GraphQL也提供了接口,即包含了type必须实现的、确定的、field的集合的抽象的type。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    interface Character {
    id: ID!
    name: String!
    friends: [Character]
    appearsIn: [Episode]!
    }
    type Human implements Character {
    id: ID!
    name: String!
    friends: [Character]
    appearsIn: [Episode]!
    starships: [Starship]
    totalCredits: Int
    }
  • 结合(union):结合和接口非常类似,只是没有具体说明type之间的共同field,即没有将type的具体属性抽象出来

    1
    union SearchResult = Human | Droid | Starship
  • 输入(input):当你可能要传递整个对象(例如参数为一个对象时),需要指定这个对象的type,就可以使用input。简单的把type换成input即可

    1
    2
    3
    4
    input ReviewInput {
    stars: Int!
    commentary: String
    }

上面就是GraphQL中一些基础概念,更加进阶的概念会在以后的文章中提到。

GraphQL对比RESTful

一万个人心中有一万种RESTful,RESTful虽然简单易理解,但是在深入开发的过程中其难扩展的缺点逐渐暴露了出来。

例如前面官网上的例子,GraphQL会直接返回这样的结果

1
2
3
4
5
6
7
8
9
10
11
12
{
"data": {
"hero": {
"name": "Luke Skywalker"
"friends": [
{ "name": "Han Solo" },
{ "name": "R2-D2" },
{ "name": "Leia Organa" },
]
}
}
}

而RESTful,可能有人会这样写

1
2
3
GET /hero/
#之后遍历返回的信息,并发送新请求
GET /hero/加上前一次查询返回的name/friends/

或者

1
GET /heros?extend_query=friends

这种情景下,RESTful可能会去发送多次请求,或者把请求魔改得不直观。GraphQL恰恰能很好的解决这类问题。

同时我们也看到了,GraphQL在一定程度上,查询请求是不依赖url的,这也许意味着当系统要添加新的功能,同时需要的数据能用之前的数据组装,就不需要新的后台接口了。

此外,若是后台能将数据拆分,提供大量的原子数据接口的话,那么对于产品版本迅速迭代将是一件非常有意义的事情。

Relay简介


Relay是一个用于构建数据驱动的React应用的框架,结合GraphQL可以实现用GraphQL声明需要的数据,Relay指明在什么时机用什么方法去获取数据。
Relay还能综合所有query,利用高效的网络请求去获取你恰好需要的数据,也能结合GraphQL的mutation去修改客户端/服务端上的数据,并且同时提供了自动化的连贯的数据更新机制和错误处理机制。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2018 香香鸡的小窝 All Rights Reserved.

SunskyXH hold copyright