TanStack Query stellt jeder Query-Funktion eine AbortSignal-Instanz zur Verfügung. Wenn eine Query veraltet oder inaktiv wird, wird dieses Signal abgebrochen. Das bedeutet, dass alle Queries abgebrochen werden können, und Sie können bei Bedarf auf den Abbruch innerhalb Ihrer Query-Funktion reagieren. Das Beste daran ist, dass Sie weiterhin die normale async/await-Syntax verwenden können und gleichzeitig alle Vorteile des automatischen Abbruchs nutzen.
Die AbortController-API ist in den meisten Laufzeitumgebungen verfügbar. Wenn Ihre Laufzeitumgebung sie nicht unterstützt, müssen Sie ein Polyfill bereitstellen. Es gibt mehrere verfügbare.
Standardmäßig werden Queries, die vor der Auflösung ihrer Promises ausgemountet oder ungenutzt werden, *nicht* abgebrochen. Das bedeutet, dass nach der Auflösung des Promises die resultierenden Daten im Cache verfügbar sind. Dies ist hilfreich, wenn Sie mit dem Empfang einer Query begonnen haben, aber die Komponente vor Abschluss ausgemountet haben. Wenn Sie die Komponente erneut mounten und die Query noch nicht aus dem Garbage Collector entfernt wurde, sind die Daten verfügbar.
Wenn Sie jedoch das AbortSignal verbrauchen, wird das Promise abgebrochen (z. B. das Abbrechen des Fetch) und daher muss auch die Query abgebrochen werden. Das Abbrechen der Query führt dazu, dass ihr Status auf ihren vorherigen Zustand *zurückgesetzt* wird.
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const todosResponse = await fetch('/todos', {
// Pass the signal to one fetch
signal,
})
const todos = await todosResponse.json()
const todoDetails = todos.map(async ({ details }) => {
const response = await fetch(details, {
// Or pass it to several
signal,
})
return response.json()
})
return Promise.all(todoDetails)
},
})
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const todosResponse = await fetch('/todos', {
// Pass the signal to one fetch
signal,
})
const todos = await todosResponse.json()
const todoDetails = todos.map(async ({ details }) => {
const response = await fetch(details, {
// Or pass it to several
signal,
})
return response.json()
})
return Promise.all(todoDetails)
},
})
import axios from 'axios'
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) =>
axios.get('/todos', {
// Pass the signal to `axios`
signal,
}),
})
import axios from 'axios'
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) =>
axios.get('/todos', {
// Pass the signal to `axios`
signal,
}),
})
import axios from 'axios'
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) => {
// Create a new CancelToken source for this request
const CancelToken = axios.CancelToken
const source = CancelToken.source()
const promise = axios.get('/todos', {
// Pass the source token to your request
cancelToken: source.token,
})
// Cancel the request if TanStack Query signals to abort
signal?.addEventListener('abort', () => {
source.cancel('Query was cancelled by TanStack Query')
})
return promise
},
})
import axios from 'axios'
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) => {
// Create a new CancelToken source for this request
const CancelToken = axios.CancelToken
const source = CancelToken.source()
const promise = axios.get('/todos', {
// Pass the source token to your request
cancelToken: source.token,
})
// Cancel the request if TanStack Query signals to abort
signal?.addEventListener('abort', () => {
source.cancel('Query was cancelled by TanStack Query')
})
return promise
},
})
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ 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()
})
},
})
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ 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()
})
},
})
Ein AbortSignal kann in der Client-Methode request gesetzt werden.
const client = new GraphQLClient(endpoint)
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) => {
client.request({ document: query, signal })
},
})
const client = new GraphQLClient(endpoint)
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) => {
client.request({ document: query, signal })
},
})
Ein AbortSignal kann im Konstruktor von GraphQLClient gesetzt werden.
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) => {
const client = new GraphQLClient(endpoint, {
signal,
})
return client.request(query, variables)
},
})
const query = useQuery(() => {
queryKey: ['todos'],
queryFn: ({ signal }) => {
const client = new GraphQLClient(endpoint, {
signal,
})
return client.request(query, variables)
},
})
Möglicherweise möchten Sie eine Query manuell abbrechen. Wenn eine Anfrage beispielsweise lange dauert, können Sie dem Benutzer ermöglichen, auf eine Abbrechen-Schaltfläche zu klicken, um die Anfrage zu stoppen. Dazu müssen Sie nur queryClient.cancelQueries({ queryKey }) aufrufen. Dies bricht die Query ab und setzt sie in ihren vorherigen Zustand zurück. Wenn Sie das an die Query-Funktion übergebene Signal verbraucht haben, wird TanStack Query zusätzlich auch das Promise abbrechen.
const query = useQuery({
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
},
})
const queryClient = useQueryClient()
function onButtonClick() {
queryClient.cancelQueries({ queryKey: ['todos'] })
}
const query = useQuery({
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const resp = await fetch('/todos', { signal })
return resp.json()
},
})
const queryClient = useQueryClient()
function onButtonClick() {
queryClient.cancelQueries({ queryKey: ['todos'] })
}
Abbruch-Optionen werden verwendet, um das Verhalten von Query-Abbruchvorgängen zu steuern.
// Cancel specific queries silently
await queryClient.cancelQueries({ queryKey: ['posts'] }, { silent: true })
// Cancel specific queries silently
await queryClient.cancelQueries({ queryKey: ['posts'] }, { silent: true })
Ein Objekt für Abbruch-Optionen unterstützt die folgenden Eigenschaften
Der Abbruch funktioniert nicht, wenn mit Suspense-Hooks gearbeitet wird: useSuspenseQuery, useSuspenseQueries und useSuspenseInfiniteQuery.