取消查询
Quaere 为每个查询函数提供了一个 AbortSignal
实例 (opens in a new tab)。当查询变得过时或不活动时,此 signal
将被中止。这意味着所有查询都可以被取消,如果需要,您可以在查询函数内部响应取消。最重要的是,它允许您继续使用正常的异步/等待语法,同时获得自动取消的所有好处。
AbortController
API 在大多数运行环境 (opens in a new tab)中可用,但如果您的运行环境不支持它,您需要提供一个 polyfill。有几个可用 (opens in a new tab)。
默认行为
默认情况下,在承诺解决之前卸载或变得未使用的查询 不会 被取消。这意味着在承诺解决后,结果数据将在缓存中可用。如果您开始接收查询,然后在完成之前卸载组件,这是有帮助的。如果再次挂载组件而查询尚未被垃圾回收,数据将可用。
但是,如果您使用AbortSignal
,则 Promise 将被取消(例如,中止获取操作),因此查询也必须被取消。取消查询将导致其状态被 还原 到先前的状态。
使用 fetch
query({
fetcher: async (variables, { signal }) => {
const todosResponse = await fetch("/todos", {
// 将 signal 传递给一个 fetch
signal,
});
const todos = await todosResponse.json();
const todoDetails = todos.map(async ({ details }) => {
const response = await fetch(details, {
// 或将其传递给多个
signal,
});
return response.json();
});
return Promise.all(todoDetails);
},
});
使用 axios
v0.22.0+ (opens in a new tab)
import axios from "axios";
query({
fetcher: (variables, { signal }) =>
axios.get("/todos", {
// 将 signal 传递给 `axios`
signal,
}),
});
使用 XMLHttpRequest
query({
fetcher: (variables, { signal }) => {
return new Promise((resolve, reject) => {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", () => {
resolve(JSON.parse(oReq.responseText));
});
signal?.addEventListener("abort", () => {
oReq.abort();
reject();
});
oReq.open("GET", "/todos");
oReq.send();
});
},
});
使用 graphql-request
可以在客户端的 request 方法中设置 AbortSignal。
const client = new GraphQLClient(endpoint);
query({
fetcher: (variables, { signal }) => {
client.request({ document: query, signal });
},
});
手动取消
您可能希望手动取消查询。例如,如果请求花费很长时间才能完成,您可以允许用户单击取消按钮来停止请求。要做到这一点,您只需调用 queryClient.cancelQueries({ query })
,这将取消查询并将其还原回其先前的状态。如果您已使用传递给查询函数的 signal,Quaere 还将取消 Promise。
const todosQuery = query({
fetcher: async ({ signal }) => {
const resp = await fetch("/todos", { signal });
return resp.json();
},
});
const queryClient = useQueryClient();
return (
<button
onClick={(e) => {
e.preventDefault();
queryClient.cancelQueries({ query: todosQuery });
}}
>
取消
</button>
);