Open creeperyang opened 7 years ago
GraphQL 快速入门 在上面一段差不多可以结束了,一个对 GraphQL 没有概念的同学读后可以有基本的印象,也可以稍微写一些相关代码——即快速上手的目的达成。
但平心而论,希望扎实掌握还是需要补一补基础,在公司内部某个应用实践 GraphQL 之后,加上读了一些资料,下面还是补冲更多的基础知识。
在 GraphQL 官网我们可以看到大大的标题:A query language for your API。GraphQL 首先是一个用于 API 的查询语言,同时也是服务端用于解析查询,返回数据的运行时。我们首先从查询语言这个角度入手。
一个最基本的查询:
// 请求
{
user {
name
}
}
把这个查询从浏览器发给后端,那么后端 GraphQL 服务会返回:
// 返回
{
data: {
user: {
name: "Lee Byron"
}
}
}
是不是非常简单直观(我们暂时不考虑后端实现)?
稍微加一点难度,假设后端有这样的数据:
[
{id: 1, name: "Lee Byron"},
{id: 2, name: "Sam"}
]
我们希望查询 id: 1
的用户的姓名,怎么来(怎么运用参数查询)?
query FetchUser {
user(id: 1) {
name
}
}
是不是还是很简单?可能不是,这里引入了一些新概念,下面一一解释:
query
是什么?是 operation,在 GraphQL 中有 query|mutation
两种操作。顾名思义,query
是查询,mutation
是插入/更新/删除操作。
FetchUser
是 query 的名字,可任意取。好的名字可以提示其它开发这这个 query 是做什么的。
user
是 field (字段),而 name
是 sub-field (子字段)。
id: 1
是参数(argument on the user field)。参数是无所谓顺序的,(id: 1, name: "Mike")
和 (name: "Mike", id: 1)
对 GraphQL 服务器来说是一样的。
以上所有称为一个 document (文档)。
当一个 query 没有 参数 或 directives
或 名字,那么关键字 query
可以省略,如我们开头所示。
现在我们更深入一点 Query。
接着上面的例子:
// Request
query FetchUser {
user(id: 1) {
name
}
}
// Response:
{
data: {
user: {
name: "Lee Byron"
}
}
}
假如我们想一次查询获取多个用户呢?现在 data
已经有个 user
属性了,多个用户怎么办?
所以我们引入 别名:你可以给任意 field 一个有效的 name,然后数据就会匹配到这个 name 上。
// Request
query FetchLeeAndSam {
lee: user(id: 1) {
name
}
sam: user(id: 2) {
name
}
}
// Response:
{
data: {
lee: {
name: "Lee Byron"
},
sam: {
name: "Sam"
}
}
}
可以看到,原来的 user
被换成了各自的别名。
同时,这里提一下,query 中每个字段我们都可以用逗号来分隔,不过这是可选的,看个人爱好:
query {
user {
name,
age
}
}
假设产品经理突然希望每个用户的 email 也要获取,我们可能要这样做:
// Request
query FetchLeeAndSam {
lee: user(id: 1) {
name
email
}
sam: user(id: 2) {
name
email
}
}
可以看到,我们在重复自己。假设我们又要添加属性呢?我们需要 fragment
来解决这个问题:
// Request
query FetchWithFragment {
lee: user(id: 1) {
...UserFragment
}
sam: user(id: 2) {
...UserFragment
}
}
fragment UserFragment on User {
name
email
}
// Response:
{
data: {
lee: {
name: "Lee Byron",
email: lee@example.com
},
sam: {
name: "Sam",
email: sam@example.com
}
}
}
...
是 spread 操作符,跟 ES6 语法类似。on User
表明 UserFragment
只能运用在 User
类型上。 Inline Fragment
用于根据运行时的类型有条件地得到类型。
query inlineFragmentTyping {
shows(titles: ["The Matrix", "Mr. Robot"]) {
title
... on Movie {
sequel {
name
date
}
}
... on Tvshow {
episode {
name
date
}
}
}
}
Movie
类型,所以会得到 sequel
数据;Tvshow
类型,所以会得到 episode
数据。如果我们需要一种方法去动态更改 query 的结构和形状,比如 include/skip 某个字段,那么指令(Directives)就是我们所需要的。
现在 GraphQL 提供 @include
和 @skip
两种指令(之后可能会更多)。
@include(if: Boolean)
仅仅在参数为 true
时包括这个字段。@skip(if: Boolean)
仅仅在参数为 true
时剔除这个字段。如果两个指令在某个字段上都出现,那么只有在 (skip: false) && (include: true)
时才包括这个字段。
query myQuery($someTest: Boolean) {
experimentalField @include(if: $someTest)
}
学习了
GraphQL 简介
GraphQL 是一种 API 查询语言,同时也是基于 自定义类型系统 执行查询的一个服务端运行时(runtime) 。GraphQL 本身不绑定任何数据库或存储引擎,而是可以在现有代码和数据上提供支持。
介绍概念后,一般应该紧跟介绍 GraphQL 的特性,跟前辈 Restful API 的比较等等。不过我觉得对初学者来说(包括我),这样的先后顺序并不友好,特别是对 GraphQL 这样全新的技术,以 demo 来快速了解怎么用,有个大概印象会更好。
所以下面紧接 GraphQL 的应用。
GraphQL 使用
所有示例基于 GraphQL 的 node.js 实现(graphql-js),请确保已安装以下依赖:
node>=6
npm install graphql
,GraphQL 的 JS 实现,提供了两个重要能力:创建 type schema 和 对对应的 schema 执行查询。npm install express express-graphql
,创建 GraphQL HTTP server。1. 最简示例
GraphQL 查询本质是客户端发送字符串到服务端,服务端解析后返回 JSON 给客户端。下面我们尝试构建最基本的 查询。
这个例子中没有引入客服端和服务端的区分,只是展示了怎么创建 Schema ,query 怎么被处理。下面一个例子结合 express 构建一个正常的 GraphQL 服务。
2. 集成 GraphQL 服务端
服务端使用
express
和express-graphql
搭建 GraphQL 服务。客户端代码:
上面代码中我们展示了怎集成
express-graphql
,前端怎么向后台发起查询等等。需要注意到基本类型有:
String, Int, Float, Boolean, ID
5种,我们试验了String|Float|Int
等 3 种。其中ID
对应 JavaScript 中的Symbol
。默认情况下,指定基本类型时返回
null
是合法的。但如果在后面加上感叹号则表示不允许为空,比如这里的Float!
。给基本类型加上方括号则表示为数组,如
[Int]
。此外,查询时可以使用参数,参数用圆括号包裹,如
rollDice(numDice: 3, numSides: 6)
。当然,有时候我们可能不希望把参数直接写死,那么可以这样传参: