同学 GraphQL 了解一下:基础篇

发布于 2023-08-14 20:05:32 字数 5684 浏览 41 评论 0

GraphQL 由 Facebook 发起,其手机客户端自 2012 年起,就全面采用了 GraphQL 查询语言, 2015 年, Facebook 全面开源了第一份 GraphQL 规范。到目前为止,在 Twitter,Github,Pinterest,Shopify 等大型网站也得到了广泛的实践。语言也从最初的 js,扩展到 java ,python,Go。

且 Apollo-client 也逐渐做全了 graphql 生态。
GraphQL 是一种用于 API 的查询语言(规范),是一种协议而非存储。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余;

如果想在读下面的知识之前,对 GraphQL 先有一个粗狂的认识,可以登录 GitHub GraphQL API 站点,体会一下其使用,可点击右侧的 Doc 文档查看接口定义。

GraphQL 出现的意义


上面是一张我们常用的 Restful 接口交互(上)和引入 GraphQL 接口中间层的接口(下)交互对比图,在此之前,我们先了解一下当前我们所使用的 Restful 接口的痛点:

  1. 冗余字段大量返回;
  2. 渲染一个复杂的页面需要发起多个请求;
  3. API 定义文档更新不及时;
    相信上面的三点,在前端淌过水的你,一定是会有体会的。一个接口,同时用于 h5 页面和 web 页面的渲染源数据,但可能 H5 页面只需要这些数据源的 1/10,冗余数据的返回浪费了流量,消耗了时间;由于现在后端更推崇 microservice,提供聚合服务的 API 被认为没有技术含量,所以我们有时渲染一个关系复杂的页面,需要请求 5,6 次,才能完整的渲染出一个页面,这期间我们还得去容错,避免因其中某一个请求的失败导致页面无法渲染的问题;API 文档更新不及时,相信这是最常见的吐槽,好好的静态页面写完,并自己照着 API 文档做完 mock,等联调时,接口返回的字段完全不按 API 定义来,奔溃。

    上图摘自 GraphQL 官网,其用简单的三句话:描述你的数据(服务端),请求你所要的数据(客户端),得到可预测的结果。其隐藏的意思就是:
  4. 服务端(或则中间层)需要描述所有可能的类型系统(Schema),有一定工作量;
  5. 按你所需请求你需要的数据,这就解决了不同客户端,不同的渲染需求,都请求回同样的数据源的痛点;
  6. 获取多个资源只用一个请求,除了你可以描述你某个请求需要返回那些字段,你还可以定义这个请求需要返回那些数据。对应浏览器来讲,只发送了一个请求,GraphQL 服务端会根据请求定义将这些请求拆分,并最后再将数据拼装返回回来;
    听起来是不是特别爽,那实现起来呢?

零碎的 GraphQL 语法

基础语法

其实 GraphQL 所需要学习的语法很少,大部分语法与我们平时的语法一致,可以通过 官网 详细了解。首先,GraphQL 是一门强类型语言,所以和我们在数据库定义一张表一样,我们需要定义每一个属性的类型.如下所示:

        enum Episode {
          NEWHOPE
          EMPIRE
          JEDI
        }
        type Person{
             id: ID! 
             name: String!
             friends: [Person]
             appearsIn: [Episode]! 
        }   

上面是一个简单的类型定义,先是定义了一个枚举,然后我们定义了一个类型,类型中有四个属性:id、 name、 friends、 appearsIn,其中 id 和 name 是标量类型,而 friends 是一个 Person 类型,这是一个嵌套类型,仔细想想应该没什么毛病,毕竟你的朋友和你一样,都是人;而 appearsIn 是一个枚举类型,看起来还是很熟悉的;

了解完类型,再了解一下 Arguments 和 resolver,两者都是偏服务端一些,但是了解一下,对 graphql 的使用原理有进一步的认识;

对于一个 Restful API 来讲,除了知道接口 URL,我们还需要知道接口的传参定义,对于 GraphQL 其实也一样,虽然 URL 只有一个,不同的接口通过 type 来区别,但传参同 Restful API 一样,体现了客户端与服务端的交互。比如下面,查询的目标是 id = 2 的用户,获取他的用户名:

        Query{
            user(id: 2) {
                id
                userName
            }
        }

而在服务端定义一个接口时,我们也需要去定义入参,主要从两个方面,一是类型,二是其是否必填,比如下面这样:

接口定义

user: {
  type: UserType,
  args: {
    id: { type: GraphQLID }
  },
  resolve: (root, args, context, info) => {
    const { id } = args;
    return getUser(id);
  }
}

查询定义

const schema = buildSchema(`
  type User {
    id: ID!
    userName: String,
    age: Int,
    gender: String
  }

  type Query {
    user(id: ID!): User
  }

  type Mutation {
    createMessage(input: MessageInput): Message
    updateMessage(id: ID!, input: MessageInput): Message
  }
`);

上面的代码只是定义了一个输入属性 id,并未定义其是否是必填,所以当查询时,如果没有配置查询 id,查询不会报错,只会获取一个为 null 的空值结果。但是讲道理的话,我们希望这是一个必填项,所以我们需要修改服务端的代码,将id: { type: GraphQLID } 更换为id: {type: new GraphQLNonNull(GraphQLID)},这句代码的含义就表示 id 是一个类型为 ID 的必填项,再次执行我们的查询可以得到下面的错误提示,提示 id 是一个必填的 ID 类型,同时右侧也没有获取到为空的查询结果;

在讲上面 Arguments 时候,可以零星的看到 type 中有一个 resolve 方法,其接收 root, args, context, info 四个参数。其中 root 代表这个 type 上父节点的 resolve 值(因为 GraphQL 支持嵌套查询),args 就是上面讲的,context 表在 Resolver 解析链中不断传递的中间变量,和 react 的上下文相似,而 info 这个概念,是当前 Query 的 AST 对象,比较抽象,但是可以通过查看 info,获取这个 QUERY 的编译对象。这个方法也是后端服务编写的重点部分,常常我们可以在这里与已有的 Restful API 关联起来。

核心概念

Schema 可以说是 GraphQL 最具核心的部分,其描述了整个接口向外暴露的形式;像 Restful API,我们会定义一个查询所有人的接口 url 定义为:/api/v1/user/getUsers,而查询人具体信息的接口 url 为:/api/v1/user/getUserById,而新增一个人员的接口 url 定义为:/api/v1/user/createUser,前端人员调用起来很直观。但是 graphql 是完全不一样的使用方式,其向前端暴露的 url 就一个像/api/graphql 之类的,那这么多接口怎么区分呢?

奥妙就是上面这张图,一个 graphql 接口都有一个 Schema 定义,其定义三种操作方式:query(查询),mutation(变更)和 subscription(监听)。再往下延伸,一个查询中包含多个 field,也就是多种不同的查询,比如 query user 查询人,query message 查询消息,query weather 查询天气,通过这些就实现了 Restful API 使用多个 url 来达到不同操作的效果。

总结

这是一篇自己学习 GraphQL 期间,归纳总结到的信息,自己感觉是同现在的开发方式相比,需要在前端与 Restful API 之间增加一层 GraphQL 中间层,这确实增加了工作量,但看上面提到的语法,其编程还是非常直观易懂的,在业务不是那么繁重的时候,还是值得推广的。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

财迷小姐

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文