什么是 GraphQL?
GraphQL 是一种用于 API 的查询语言。它提供了一种更有效、强大和灵活的方式来描述和查询数据。相较于传统的 RESTful API,GraphQL 的优势在于:
- 可以按需获取所需数据,避免过度获取和浪费带宽;
- 可以批量请求多个数据源,避免多次请求和等待;
- 不卡在 REST 的设计模式中,让 API 可以更灵活地和前端合作。
为什么需要数据缓存?
由于 GraphQL 的灵活性,前端可以非常方便地获取所需数据。但这也带来了一些问题:
- 每次查询都需要向后端发送请求,无法利用本地的缓存数据;
- 当查询参数不变时,也需要重新发送请求,即使缓存中已经有相同的数据。
因此,GraphQL 实现了一套数据缓存方案,以提高数据利用率和减少网络请求。GraphQL 的缓存方案的主要思路是将查询语句和结果的哈希值作为查询的唯一索引,以此来缓存查询结果。
GraphQL 数据缓存的具体实现
GraphQL 的数据缓存主要由以下两部分实现:
哈希函数的实现
哈希函数用来将查询语句和结果的哈希值进行计算和比较。GraphQL 采用了 MurmurHash3 这个高效的哈希算法,用法如下:
// javascriptcn.com 代码示例 import MurmurHash3 from 'murmurhash3' const query = ` query { user(id: 123) { name age } } ` const variables = {} const hash = MurmurHash3.x86.hash128(`${query}:${JSON.stringify(variables)}`)
其中 query
是查询语句,variables
是查询参数。以上代码可以将查询语句和参数进行哈希,得到一个唯一的哈希值。哈希值可以作为查询的缓存索引,以此来判断查询是否存在缓存中。
缓存机制的实现
缓存机制分为两部分:读取缓存和写入缓存。
读取缓存
GraphQL 的缓存机制提供了 readQuery
和 readFragment
两个方法用于读取缓存。
readQuery
方法用于读取整个查询的结果,例如:
// javascriptcn.com 代码示例 const user = client.readQuery({ query: gql` query { user(id: 123) { name age } } `, })
user
将会是查询到的数据对象,如果没有缓存则为 null
。
readFragment
方法用于读取部分查询的结果,例如:
const userAge = client.readFragment({ id: 'User:123', fragment: gql` fragment UserAge on User { age } `, })
id
是要读取数据的对象的唯一标识符,fragment
是数据的结构。此代码会读取 User:123
用户对象的年龄属性。
写入缓存
GraphQL 的缓存机制也提供了 writeQuery
和 writeFragment
两个方法用于写入缓存。
writeQuery
方法用于将整个查询的结果写入缓存,例如:
// javascriptcn.com 代码示例 const data = { user: { __typename: 'User', id: 123, name: 'Tom', age: 20, }, } client.writeQuery({ query: gql` query { user(id: 123) { name age } } `, data, })
以上代码会将 data
对象写入缓存中。
writeFragment
方法用于将部分查询的结果写入缓存,例如:
// javascriptcn.com 代码示例 client.writeFragment({ id: 'User:123', fragment: gql` fragment UserAge on User { age } `, data: { __typename: 'User', age: 21, }, })
以上代码会将 User:123
用户对象的年龄属性更新为 21。
实际应用举例
下面是一个实际应用的举例:
// javascriptcn.com 代码示例 import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client' import { gql } from '@apollo/client/core' import MurmurHash3 from 'murmurhash3' const httpLink = new HttpLink({ uri: 'https://api.example.com/graphql', }) const cache = new InMemoryCache() const client = new ApolloClient({ link: httpLink, cache, }) const query = gql` query { user(id: 123) { name age } } ` const variables = {} const hash = MurmurHash3.x86.hash128(`${query}:${JSON.stringify(variables)}`) const user = client.readQuery({ query, }) if (!user) { const { data } = await client.query({ query, variables }) client.writeQuery({ query, data }) }
以上代码将会按需获取用户 123 的名称和年龄属性。如果查询已经在缓存中,则会直接读取缓存;如果没有缓存,则会发送查询请求,并将结果写入缓存中,下次查询可以直接从缓存中读取。
总结
GraphQL 的数据缓存方案主要是通过哈希算法和缓存机制来实现的。通过哈希算法可以将查询语句和结果的哈希值进行计算和比较,以此来判断查询是否存在缓存中;通过缓存机制可以将查询结果写入缓存中,以此来减少网络请求和提高数据利用率。前端可以利用这个缓存方案,提高查询的速度和性能。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652a59957d4982a6ebcaedce