GraphQL 入门: Apollo Client 查询(Batching)合并

GraphQL 入门: 简介
GraphQL 入门: Apollo Client - 简介
GraphQL 入门: Apollo Client - 安装和配置选项
GraphQL 入门: Apollo Client - 连接到数据
GraphQL 入门: Apollo Client - 网络层
GraphQL 入门: Apollo Client - 开发调试工具
GraphQL 入门: Apollo Client - 持久化GraphQL查询概要
GraphQL 入门: Apollo Client - 存储API
GraphQL 入门: Apollo Client - 查询(Batching)合并

当打开一个客户端页面的时候,客户端可能会触发多个请求以完成数据的加载. 有可能会超出浏览器并发连接的数目,为了解决这个问题,我们通过Query batching一次的请求完成页面需要的所有数据.

Query batching 就是在单个请求中包含多个查询的技术,它有几个极其显著的优点:

使用

假设一个场景,多个UI组件都是用了GraphQL查询从服务器获取数据. 下面两个查询可能是由两个不同的UI组件生产的,会产生两次客户端和服务器之间的数据往返.

client.query({ query: query1 })
client.query({ query: query2 })

在Apollo Client中,查询批处理认是关闭的. 要打开查询批处理,需要在初始化 Apollo Client的时候打开 shouldBatch 选项:

const client = new ApolloClient({
    // ... 其他选项
    shouldBatch: true
});

时间间隔

时间间隔标识在一个特定的时间段内(比如100ms),如果客户端产生了多个查询,那么Apollo Client会自动把多个查询合并为一个.

查询合并

查询合并是由 BatchednetworkInterface 进行合并的,下面举例说明,现在要执行两个GraphQL查询:

query firstQuery {
   author {
    firstName
    lastName
  }
}
query secondQuery {
  fortuneCookie
}

我们想象一下合并的问题,假设上面的两个查询会合并成如下的样子:

query ___composed {
  author {
    firstName
    lastName
  }
  fortuneCookie
}

但是,上述合并后的查询有几个问题

  • 依据GraphQL规范,查询字段名称是不能相同的,否则会产生命名冲突,解决这个问题的办法是使用 alias(别名) 来保证可以合并任意查询同时不会让字段名字发生名称冲突.

    query ___composed {
      aliasName: author {
        firstName
        lastName
      }
    }
  • 调试的时候服务器应答的字段名称和客户端的原始名称不一致,给调试带来麻烦,解决办法是在网络层进行查询的合并. 当前大多数GraphQL客户端实现中,请求时以如下格式发送到服务器的:

    {
      "query": “< query string goes here >”,"variables": {
        <variable values go here>
      }
    }

网络层的查询合并

网络层的查询合并,只需要用createBatchingNetworkInterface 替换 createNetworkInterface 即可. 例如:

import ApolloClient,{ createBatchingNetworkInterface } from 'apollo-client';
const batchingNetworkInterface = createBatchingNetworkInterface({
  uri: 'localhost:3000',batchInterval: 100,opts: {
    // Options to pass along to `fetch`
  }
});
const apolloClient = new ApolloClient({
  networkInterface: batchingNetworkInterface,});
// These two queries happen in quick succession,possibly in totally different
// places within your UI.
apolloClient.query({ query: firstQuery });
apolloClient.query({ query: secondQuery });

结语

上述Batching查询是正对HTTP这种无状态协议的,目的是为了减少重复建立新的TCP连接消耗的时间,如果采用Websocket这种有状态协议,就没有必要在使用Query Batching,采用GraphQL Subscriptions.

参考资料

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...