该系列其他文章可以点击查看专栏:react-query手把手教程
介绍
如果组件中的查询在卸载前未完成数据加载,那么react-query
将会自动取消该请求。或者某个查询键在获取数据的过程中有更改,此时数据请求也会被取消(因为更改查询键后,之前的数据实际上来说已经没有用处了)。
所以在大多数情况下,你不需要手动去取消请求。
取消请求可以节省用户和服务器的网络资源。如果请求在发送之前被取消的话,服务器就无需进行响应;即使服务器响应了请求并返回了结果,客户端其实也不需要花费资源去处理后端数据。因此取消查询对于提升用户体验及性能非常有帮助。
实践
AbortController
事件监听
react-query使用AbortController
API来控制取消,库已经封装好相关调用,你只需接收相关取消信号即可。
有兴趣的同学,可以阅读这些扩展资料:
获取取消信号的操作,通常在一些需要获取数据后执行异步操作的流程中非常实用。现在举个例子:假如需要在请求结束后,通过setTimeout
执行后续的一些操作,如果该请求被取消,那么就取消应该setTimeout
操作,伪代码如下:
const DelayComponent = () => {
const delayQuery = useQuery(
["delay"],
// ①
({signal}) => {
let timeout;
const delayPromise = new Promise(resolve => {
timeout = setTimeout(() => resolve("Hello"), 1000);
})
// ②
signal?.addEventListener("abort", () => {
clearTimeout(timeout);
});
return delayPromise;
})
// ...
}
①:可以看到上面的例子传入的执行查询的方法中,解构出了react-query的signal
,它是AbortSignal实例化后的结果。
你可以在②中直接监听其abort
事件来知道,当前请求已被取消,需要将相关后续异步操作一并清除掉。
用户手动取消请求
fetch
与AbortController
将实例化后的AbortController
传入fetch时,一旦手动触发取消请求,fetch将会立即取消本次的请求,无需做其它的设置。例子如下:
const userQuery = useQuery(
["users"],
({signal}) => fetch("/api/users", {signal})
.then(res => res.json())
);
手动调用取消
可以为用户提供手动取消请求的按钮,只需要调用queryClient
中的cancelQueries
方法来取消当前正在请求的查询。请注意,调用时需要传入查询键过滤器(因此其实可以批量取消)。比如下面这个例子:
import { useQueryClient, useQuery } from 'react-query'
const Users = () => {
const queryClient = useQueryClient();
const userQuery = useQuery(
["users"],
// ②
({signal}) => fetch("/api/users", {signal})
.then(res => res.json())
);
return (
<div>
// ①
<button onClick={() => queryClient.cancelQueries(["users"])}>
取消请求
</button>
<div>
{/* ... */}
</div>
</div>
)
}
当用户取消请求时,["users"]
查询将会被自动终止。
可以看到在这里将实例化后的AbortController
:signal
解构出来后,传入了fetch
的参数中,当fetch
接收到了用户主动取消的信号时,将会自动取消当前的请求。
这里需要注意以下几个点:
- 如果手动取消已有缓存的查询,react-query将会继续返回缓存中之前存储的过期信息
- 如果接口是在第一次请求时被取消,那么该查询如果没有满足任何重新获取的条件下,将会永远不会被调用,并且当前的状态为
idle
,直到查询重新被获取
总结
react-query
底层依赖AbortController
来实现取消请求的能力- 可以监听实例化后
AbortController
的abort
事件来监听当前请求是否被取消 fetch
可以将传入实例化后的AbortController
作为singal
参数传入,一旦用户触发取消时间,请求将会被取消queryClient.cancelQueries
传入查询过滤器可批量取消请求
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情