javascript / expert
Snippet
Managing Asynchronous Race Conditions using WatchEffect AbortSignal
When triggering asynchronous network requests inside reactive watchers, rapid state updates cause race conditions where stale requests overwrite newer responses. Vue's watchEffect passes an onCleanup registration function that allows attaching an AbortController signal. When the tracked reactive dependency changes before the previous promise resolves, the cleanup callback executes abort(), cancelling the outgoing HTTP request and ignoring AbortError exceptions safely.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { watchEffect, ref } from 'vue';const query = ref('');const result = ref(null);watchEffect(async (onCleanup) => {const controller = new AbortController();onCleanup(() => controller.abort());try {const response = await fetch(`/api/search?q=${query.value}`, {signal: controller.signal});if (!response.ok) throw new Error(`HTTP status ${response.status}`);result.value = await response.json();} catch (err) {if (err.name !== 'AbortError') {console.error('Fetch operation failed:', err);}}});
vue
Breakdown
1
watchEffect(async (onCleanup) => {
Registers a reactive effect that automatically tracks dependencies and accepts an onCleanup registration callback.
2
const controller = new AbortController();
Instantiates a DOM AbortController to manage cancellation of the pending fetch request.
3
onCleanup(() => controller.abort());
Schedules controller.abort() to fire whenever the effect re-runs or the underlying scope unmounts.
4
signal: controller.signal
Binds the AbortSignal object directly to the fetch options array to allow network-level cancellation.
5
if (err.name !== 'AbortError') {
Filters out intentional cancellation signals so only actual runtime network or HTTP errors are logged.