1

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


FigoZhu
58 声望1 粉丝