广告
Vue.js 小书已经出版,尤小右作序推荐:http://www.ituring.com.cn/boo…
欢迎购买。
Swift iOS 小书 http://www.ituring.com.cn/boo…
正文
GraphQL 原来 2012 年就已经开源,算来也有不少历史了,但是看起来网络资料并不太多,大家普遍还是觉得麻烦。单单看官方手册好像就太不亲人的,太容易从自己的角度去描述细节,而不是从使用的角度去剖析,这也是官方手册普遍的问题。
比如“获取多个资源,只用一个请求”,官方说:
GraphQL 查询不仅能够获得资源的属性,还能沿着资源间引用进一步查询。典型的 REST API 请求多个资源时得载入多个 URL,而 GraphQL 可以通过一次请求就获取你应用所需的所有数据。这样一来,即使是比较慢的移动网络连接下,使用 GraphQL 的应用也能表现得足够迅速。
因为他假设你知道 REST API,并且和它对比。其实,认识一个新事物,认识它本身会更直接,认识清楚了,想要对比了再去对比才有价值。但是人们太喜欢使用类别了。
我曾经写过一个高点击率的文章,讲述了 vuex 是什么,因为大家普遍反映官方文档不好懂,原因是是它上来和 reactive 那套东西对比。作者这样做可以理解,因为他就是对比着做的,说出来的也是对比的话,也认为这是干货。但是读者就不太好了解,因为我 vue 还没有搞利索,现在你让我搞搞 reactive 才能动 vue 的东西。这很令人绝望。
我们还是从一个案例开始。假设我有两个数据实体,一个是 book,一个是 author,且 book 和 author 是 1: 对多的关系。它的数据样本,看起来是这样的:
var books = [{id:0,title:"null book",author:{name:"reco"}},
{id:1,title:"the little prince",author:{name:"reco"}},
{id:2,title:"the http book",author:{name:"reco"}}]
var authors = [{id:1,name:"reco",books:[{title:"the little prince"},{title:"the http book"}]},
{id:2,name:"rita",books:[{title:"the swift book"}]}]
就是这样的数据源。如果使用 Graphql 来做查询,可以查询作者列表,且对作者对书籍的引用做进一步查询,也就是希望这样的查询:
{authors{name,books{title}}}
可以返回:
{
"data": {
"authors": [
{
"name": "reco",
"books": [
{"title": "the little prince"},
{"title": "the http book"}
]
},
{
"name": "rita",
"books": [
{"title": "the swift book"}
]
}
]
}
}
对 author.name 的查询,就是获取对象属性,是比较容易的,而对而对关联对象的延伸查询,其实和属性一模一样,只不过看起来是嵌套的而已。
明确了目标,我们把代码跑起来,也还是 typeDefs+resolvers 的一套东西:
const typeDefs = `type Book {
title: String
author: Author
}
type Author {
name: String
books: [Book]
}
type Query {books:[Book]
single(id:String):Book
authors:[Author]
}`
resolvers = {
Query:{// {books{title}}
async books(root,{},context) {return books},
// {authors{name,books{title}}}
async authors(root,{},context) {return authors},
// {single(id:"2"){title,author{name}}}
async single(root,{id},context){for (var i = 1; i < books.length; i++) {var item = books[i]
if (item.id == id)return item;
}
return books[0]
},
},
}
你可以把它先跑起来,完整代码在这里。你可以在 localhost:4000/graphql 内输入 {authors{name,books{title}}},了解查询的结果。然后再看代码,它简单到不必解释。
如果换成 RESTAPI,那么你需要定义的是这样的资源,book 和 author 在 REST 内就被称为资源:
GET /book
GET /author
且仅仅看这个资源,作为开发者,是无法知道 book 会返回哪些属性的,当然也无法从定义上看到 author 后面有 book 还是没有,你必须有手册去告诉开发者。如果没有,是否应该自己去查询 book 资源,如果有,那么和 book 资源查询重复,所以,实践上来说,常常是分别定义,自己查自己的。为了效率才会不在乎重复。官方说:“典型的 REST API 请求多个资源时得载入多个 URL”。
另外,除非你自己解析参数,前端开发者也无法很好的告诉后端在某个场景下,他需要那些属性,那些属性他并不需要。在这里案例里面,我们可以举例说,在某个界面我只需要 author.name 属性,另外一个界面,我还额外需要 author.book.title。当然这些在 graphql 都可以做到。
使用 graphql,前端可以指定查 author.name
{authors{name}}
或者只查 author.book.title
{authors{books{title}}}
后者就是通过 author 在关联了 book,也就是 ” 还能沿着资源间引用进一步查询 ”。
回头看官方网页的这句话:比如“获取多个资源,只用一个请求”,官方说:
GraphQL 查询不仅能够获得资源的属性,还能沿着资源间引用进一步查询。典型的 REST API 请求多个资源时得载入多个 URL,而 GraphQL 可以通过一次请求就获取你应用所需的所有数据。这样一来,即使是比较慢的移动网络连接下,使用 GraphQL 的应用也能表现得足够迅速。
对比 REST,再对照可运行的代码,我想应该容易理解多了。
广告
Vue.js 小书已经出版,尤小右作序推荐:http://www.ituring.com.cn/boo…
欢迎购买。
Swift iOS 小书 http://www.ituring.com.cn/boo…