Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як у спостерігачах Vue уникнути гонитви запитів і прибрати за собою: onWatcherCleanup?

Типова задача: при зміні id завантажити дані. Якщо id змінюється швидко (користувач клацає по списку), запити летять паралельно, і відповідь на старий запит може прийти пізніше за новий - на екрані опиняться дані не того запису.

watch(id, async (newId) => {
  const response = await fetch(`/api/users/${newId}`);
  user.value = await response.json();   // може перезаписати свіжі дані старими
});

Очищення побічного ефекту. Перед наступним запуском спостерігача (і при його зупинці) Vue викликає функцію очищення - туди кладуть скасування попереднього запиту:

import { watch, onWatcherCleanup } from 'vue';

watch(id, async (newId) => {
  const controller = new AbortController();
  onWatcherCleanup(() => controller.abort());   // Vue 3.5+

  try {
    const response = await fetch(`/api/users/${newId}`, { signal: controller.signal });
    user.value = await response.json();
  } catch (error) {
    if (error.name !== 'AbortError') throw error;
  }
});

Важливо: onWatcherCleanup треба викликати синхронно, до першого await - після нього Vue вже не знає, до якого спостерігача він належить.

До Vue 3.5 - третій аргумент колбеку:

watch(id, async (newId, oldId, onCleanup) => {
  const controller = new AbortController();
  onCleanup(() => controller.abort());
  // ...
});

Цей варіант працює й зараз і не має обмеження щодо await.

Інші застосування очищення: зняти таймер (clearInterval), відписатися від WebSocket-каналу, знищити екземпляр сторонньої бібліотеки, створений для попереднього значення.

Зупинка спостерігача:

  • спостерігачі, створені синхронно в setup, зупиняються автоматично разом з компонентом;
  • створені асинхронно (після await чи в setTimeout) - ні: їх треба зупинити вручну, інакше витік пам'яті:
const stop = watch(source, callback);
stop();

У Vue 3.5 повернений об'єкт має ще й pause() і resume().

Альтернатива для даних, що залежать від параметрів, - бібліотеки на кшталт TanStack Query, що вже розв'язують гонитву, кешування й повтори.

Докладніше в документації: Спостерігачі: очищення побічних ефектів

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання