GraphQL解析粒度
引言
关于GraphQL的基础概念,可以参看前一篇文章《更轻松的使用GraphQL》。
困惑
初次看到GraphQL,很容易被它强大的介绍所吸引,但想更进一步尝试时,却会发现它的”hello world“不是很友好,容易让人打退堂鼓。
我们首先看一下官方(grpahql-js)的例子:
var schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'RootQueryType',fields: { hello: { type: GraphQLString,resolve() { return 'world'; } } } }) });
其中,resolve函数定义部分,换成更直观一些的写法(伪代码)就是:
{ // 每个field独立的resolve函数 hello: function resolve () { return 'world'; } }
这就让人很害怕了,一个数据结构中的每个成员都要定义一个resolve函数的话,工作量和开发复杂度就令人难以接受了,所以很多人看了官方README就被吓退了。
但实际上,GraphQL是可以整个对象使用一个resolve函数来获取所有field的数据,看伪代码大概就是:
{ // 整个对象使用一个resolve函数 hello,xxx,foo,... } : function resolve () { return { hello : "world",foo : "bar",... }; }
实战
我们还是以论坛帖子为例:
1. schema定义
用户定义:
# user schema type User { uid : ID! name : String! avatar : String! }
帖子定义:
# post schema type Post { pid : ID! title : String! content : String! author : User! }
2. 提供的查询方法定义
查询定义:
type Query { post(id: ID): Post }
3. 对应的resolve函数编写
'use strict' const fakeDB = require('../../fakeDB'); function fetchPostById (root,{id},ctx) { // post的查询,第二个参数是查询语句中传入的 let pid = parseInt(id); return fakeDB.getPostById(pid); } // 对post下的author字段进行查询解决的函数 function fetchUserByAuthorId (root,args,ctx) { // 执行完post的数据查询后,遇到需要author字段的情况,会再来调用本函数,root参数就是前一步查询完的post数据 let uid = root.authorId; return fakeDB.getUserById(uid); } const postReolvers = { Query : { post : fetchPostById,},Post : { // 针对嵌套的数据结构需要的解决函数 author : fetchUserByAuthorId,}; module.exports = postReolvers;
4. 查询的结果
通过上面的fetchPostById
函数,就能查询指定id的帖子详情(整个Post数据结构)了,而无需对Post的每个field分别定义resolve函数:
查询返回结果如下:
{ "data": { "post": { "pid": "1","title": "foo","content": "xxx","author": { "uid": "1","name": "Tom","avatar": "https://pre00.deviantart.net/2930/th/pre/i/2014/182/a/2/tom_cat_by_1997ael-d7ougoa.png" } } } }
结语
希望本文能对大家初步了解GraphQL有所帮助,不要被官方“hello world”给吓退了,而能够去进一步尝试一下GraphQL。
欢迎使用更简单的GraphQL封装库:easy-graphql