📅  最后修改于: 2020-10-25 05:15:27             🧑  作者: Mango
缓存是将数据存储在称为缓存的临时存储区域中的过程。当您返回到您最近访问过的页面时,浏览器可以从缓存而不是原始服务器中获取这些文件。这样可以节省您的时间,并使网络免受额外流量的负担。
与GraphQL交互的客户端应用程序负责在其末尾缓存数据。一种可能的模式是将字段(例如id)保留为全局唯一标识符。
InMemoryCache是一个标准化的数据存储,通常在GraphQL客户端应用程序中使用,而无需使用Redux等其他库。
下面给出了将InMemoryCache与ApolloClient一起使用的示例代码-
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();
const client = new ApolloClient({
link: new HttpLink(),
cache
});
InMemoryCache构造函数采用带有属性的可选config对象,以自定义缓存。
Sr.No. | Parameter & Description |
---|---|
1 |
addTypename A boolean to determine whether to add __typename to the document (default: true) |
2 |
dataIdFromObject A function that takes a data object and returns a unique identifier to be used when normalizing the data in the store |
3 |
fragmentMatcher By default, the InMemoryCache uses a heuristic fragment matcher |
4 |
cacheRedirects A map of functions to redirect a query to another entry in the cache before a request takes place. |
我们将在ReactJS中创建一个具有两个选项卡的单页应用程序-一个用于主页选项卡,另一个用于学生。学生选项卡将从GraphQL服务器API加载数据。当用户从主页选项卡导航到学生选项卡时,该应用程序将查询学生数据。结果数据将由应用程序缓存。
我们还将使用getTime字段查询服务器时间,以验证页面是否已缓存。如果从缓存返回数据,该页面将显示发送到服务器的第一个请求的时间。如果数据是对服务器的新请求的结果,它将始终显示来自服务器的最新时间。
以下是设置服务器的步骤-
创建一个文件夹cache-server-app 。从终端将目录更改为cache-server-app 。请按照“环境设置”一章中说明的步骤3到5进行操作。
在项目文件夹cache-server-app中添加schema.graphql文件,并添加以下代码-
type Query {
students:[Student]
getTime:String
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
在项目文件夹中创建一个文件resolvers.js,并添加以下代码-
const db = require('./db')
const Query = {
students:() => db.students.list(),
getTime:() => {
const today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
return `${h}:${m}:${s}`;
}
}
module.exports = {Query}
创建一个server.js文件。请参阅“环境设置”一章中的步骤8。在终端中执行命令npm start 。服务器将启动并在9000端口上运行。在这里,我们将使用GraphiQL作为客户端来测试应用程序。
打开浏览器,然后输入URL http:// localhost:9000 / graphiql 。在编辑器中键入以下查询-
{
getTime
students {
id
firstName
}
}
样本响应显示学生姓名和服务器时间。
{
"data": {
"getTime": "22:18:42",
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
},
{
"id": "S1003",
"firstName": "Kiran"
}
]
}
}
为客户端打开一个新终端。在执行客户端应用程序之前,应使服务器终端保持运行状态。 React应用程序将在端口号3000上运行,服务器应用程序在端口号9000上运行。
在客户端中,键入以下命令-
npx create-react-app hello-world-client
这将安装典型的React应用程序所需的一切。 npx实用程序和create-react-app工具创建一个名称为hello-world-client的项目。安装完成后,在VSCode中打开项目。
使用以下命令安装用于响应的路由器模块– npm install react-router-dom 。
将终端中的当前文件夹路径更改为hello-world-client。键入npm start启动项目。这将在端口3000上运行开发服务器,并将自动打开浏览器并加载索引页面。
这显示在下面给出的屏幕截图中-
要安装Apollo客户端,请打开一个新终端并位于当前项目文件夹路径中。键入以下命令-
npm install apollo-boost graphql
这将下载客户端的graphql库以及Apollo Boost软件包。我们可以通过输入npm view apollo-boost依赖项来交叉验证。这将具有许多依赖关系,如下所示-
{
'apollo-cache': '^1.1.15',
'apollo-cache-inmemory': '^1.2.8',
'apollo-client': '^2.4.0',
'apollo-link': '^1.0.6',
'apollo-link-error': '^1.0.3',
'apollo-link-http': '^1.3.1',
'apollo-link-state': '^0.4.0',
'graphql-tag': '^2.4.2'
}
我们可以清楚地看到已经安装了apollo-client库。
对于简单的react应用程序,您只需要将index.js保留在src文件夹中,将index.html保留在公用文件夹中;可以删除所有其他自动生成的文件。
目录结构如下-
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
students.js
-->package.json
添加一个附加文件students.js,其中将包含学生组件。学生详细信息是通过“学生组件”获取的。在应用程序组件中,我们正在使用HashRouter。
以下是React应用程序中的index.js-
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {HashRouter, Route, Link} from 'react-router-dom'
//components
import Students from './students'
class App extends Component {
render() {
return(
Home !!
Welcome to React Application !!
)
}
}
function getTime() {
var d = new Date();
return d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()
}
const routes =
Time from react app:{getTime()}
Home
Students
ReactDOM.render(routes, document.querySelector("#root"))
在学生组件中,我们将使用以下两种方法来加载数据-
提取API(loadStudents_noCache) -每次单击“学生”选项卡时,都会触发一个新请求。
Apollo客户端(loadWithApolloclient) -这将从缓存中获取数据。
添加一个函数loadWithApolloclient ,从服务器查询学生和时间。此函数将启用缓存。在这里,我们使用gql函数来解析查询。
async loadWithApolloclient() {
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
Fetch API是用于获取资源的简单接口。与旧的XMLHttpRequest相比,Fetch使发出Web请求和处理响应更加容易。以下方法显示了使用提取API直接加载数据-
async loadStudents_noCache() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{
getTime
students {
id
firstName
}
}`})
})
const rsponseBody = await response.json();
return rsponseBody.data;
}
在StudentsComponent的构造函数中,调用loadWithApolloClient方法。完整的Student.js文件在下面-
import React, {Component} from 'react';
import { Link} from 'react-router-dom'
//Apollo Client
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'
const client = new ApolloClient({
link: new HttpLink({uri:`http://localhost:9000/graphql`}),
cache:new InMemoryCache()
})
class Students extends Component {
constructor(props) {
super(props);
this.state = {
students:[{id:1,firstName:'test'}],
serverTime:''
}
this.loadWithApolloclient().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
}
async loadStudents_noCache() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{
getTime
students {
id
firstName
}
}`})
})
const rsponseBody = await response.json();
return rsponseBody.data;
}
async loadWithApolloclient() {
console.log("inside apollo client function")
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
render() {
return(
Time from GraphQL server :{this.state.serverTime}
Following Students Found
{
this.state.students.map(s => {
return(
-
{s.firstName}
)
})
}
)
}
}
export default Students
您可以通过从主页选项卡切换到学生选项卡来测试react应用程序。一旦学生选项卡中加载了来自服务器的数据。它将缓存数据。您可以通过多次从“家庭”标签切换到“学生”标签进行测试。输出将如下所示-
如果您首先通过输入URL http:// localhost:3000 /#/ students加载了学生页面,则可以看到react app和GraphQL的加载时间大致相同。之后,如果您切换到主视图并返回到GraphQL服务器,则时间不会改变。这表明数据已缓存。
如果在StudentComponent的构造函数中将load方法更改为loadStudents_noCache ,则输出将不会缓存数据。这显示了缓存和非缓存之间的区别。
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
从上面的输出中很明显,如果您在选项卡之间来回切换,那么来自graphql服务器的时间将始终是最晚的,这意味着未缓存数据。