javascript / intermediate
Snippet
Cancelling Stale Asynchronous Requests with AbortController in Vue Watchers
When reacting to fast search inputs in Vue, earlier network requests may finish after newer ones, causing stale data or race conditions. Using a native AbortController allows cancelling ongoing HTTP requests prior to initiating a new fetch. By filtering out AbortError in the catch block, harmless cancellation signals are ignored while true runtime errors are preserved.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { ref, watch } from 'vue';export function useUserSearch(queryRef) {const results = ref([]);const isLoading = ref(false);const error = ref(null);let abortController = null;watch(queryRef, async (newQuery) => {if (abortController) {abortController.abort();}if (!newQuery.trim()) {results.value = [];return;}abortController = new AbortController();isLoading.value = true;error.value = null;try {const res = await fetch(`/api/search?q=${encodeURIComponent(newQuery)}`, {signal: abortController.signal});if (!res.ok) throw new Error(`HTTP status: ${res.status}`);results.value = await res.json();} catch (err) {if (err.name !== 'AbortError') {error.value = err.message;}} finally {if (!abortController.signal.aborted) {isLoading.value = false;}}}, { immediate: true });return { results, isLoading, error };}
vue
Breakdown
1
if (abortController) { abortController.abort(); }
Aborts any currently active fetch request before starting a new search.
2
signal: abortController.signal
Connects the fetch request to the cancellation signal of the AbortController.
3
if (err.name !== 'AbortError') {
Ensures intentional request aborts are not treated as genuine application errors.