Отмена запросов

В библиотеке Quasar управление HTTP-запросами обычно осуществляется через встроенный или подключаемый HTTP-клиент, чаще всего axios. Одним из ключевых аспектов работы с асинхронными запросами является возможность их отмены. Это особенно важно при динамических интерфейсах, когда пользователь может быстро менять параметры запроса или покидать страницу до завершения загрузки данных.


Механизм отмены запросов

Quasar сам по себе не содержит отдельного API для отмены запросов, поэтому применяется стандартный подход через axios CancelToken или современный AbortController.

Использование CancelToken

CancelToken позволяет создавать токен отмены, который передаётся в конфигурацию запроса. Пример:

import axios from 'axios';

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/api/data', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c;
  })
})
.then(response => {
  console.log('Данные получены', response.data);
})
.catch(error => {
  if (axios.isCancel(error)) {
    console.log('Запрос отменён', error.message);
  } else {
    console.error('Ошибка запроса', error);
  }
});

// В какой-то момент можно вызвать отмену
cancel('Пользователь отменил запрос');

Ключевые моменты:

  • Переменная cancel хранит функцию для отмены запроса.
  • Проверка axios.isCancel(error) позволяет корректно обрабатывать именно отмену, отличая её от обычных ошибок сети или сервера.

Использование AbortController (рекомендованный современный способ)

Современный подход через AbortController более универсален и поддерживается нативно в браузерах:

const controller = new AbortController();

fetch('/api/data', { signal: controller.signal })
  .then(response => response.json())
  .then(data => console.log('Данные', data))
  .catch(err => {
    if (err.name === 'AbortError') {
      console.log('Запрос был отменён');
    } else {
      console.error('Ошибка запроса', err);
    }
  });

// Отмена запроса
controller.abort();

Преимущества:

  • Работает с нативным fetch без сторонних библиотек.
  • Простая интеграция с Vue-компонентами и Quasar-контейнерами.
  • Позволяет легко управлять множественными запросами через один контроллер.

Интеграция отмены запросов в Vue-компоненты

В Quasar проекты обычно используют компоненты Vue. Отмена запросов становится критичной при навигации между страницами или динамическом обновлении данных.

Пример с onBeforeUnmount для автоматической отмены:

<template>
  <q-btn label="Загрузить данные" @click="loadData" />
</template>

<script>
import { ref, onBeforeUnmount } from 'vue';
import axios from 'axios';

export default {
  setup() {
    const data = ref(null);
    let cancel;

    const loadData = () => {
      if (cancel) cancel('Предыдущий запрос отменён');

      const CancelToken = axios.CancelToken;
      axios.get('/api/data', {
        cancelToken: new CancelToken(c => (cancel = c))
      })
      .then(res => data.value = res.data)
      .catch(err => {
        if (axios.isCancel(err)) console.log(err.message);
        else console.error(err);
      });
    };

    onBeforeUnmount(() => {
      if (cancel) cancel('Компонент размонтирован');
    });

    return { data, loadData };
  }
};
</script>

Особенности интеграции:

  • Любой предыдущий запрос автоматически отменяется при новом вызове функции загрузки.
  • Размонтирование компонента приводит к отмене всех активных запросов, предотвращая утечки памяти и лишние ошибки.

Массовая отмена запросов

Для сложных интерфейсов часто нужно отменять сразу несколько запросов. С помощью AbortController это делается через один контроллер, который передаётся в несколько fetch:

const controller = new AbortController();

Promise.all([
  fetch('/api/data1', { signal: controller.signal }),
  fetch('/api/data2', { signal: controller.signal }),
])
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log(data))
.catch(err => {
  if (err.name === 'AbortError') console.log('Все запросы отменены');
});

controller.abort(); // Отмена сразу всех запросов

Практические рекомендации

  • Использовать AbortController, если проект работает с fetch, это современный и нативный подход.
  • CancelToken применяется для проектов с активным использованием axios, но он считается устаревающим.
  • Отмена запросов должна быть встроена в жизненный цикл компонентов (onBeforeUnmount) для предотвращения утечек памяти.
  • Для сложных интерфейсов лучше централизовать управление контроллерами запросов, чтобы можно было отменять все ненужные запросы одним действием.

Интеграция с Quasar Notify и Loading

Отмена запросов может быть связана с пользовательским интерфейсом:

import { Notify, Loading } from 'quasar';

const controller = new AbortController();
Loading.show();

fetch('/api/data', { signal: controller.signal })
  .then(res => res.json())
  .then(data => {
    console.log(data);
    Loading.hide();
  })
  .catch(err => {
    Loading.hide();
    if (err.name === 'AbortError') {
      Notify.create({ message: 'Загрузка отменена', color: 'negative' });
    } else {
      Notify.create({ message: 'Ошибка запроса', color: 'negative' });
    }
  });

// При необходимости отмены
controller.abort();
  • Использование Loading и Notify делает отмену запроса визуально понятной пользователю.
  • Комбинация с контроллером обеспечивает синхронизацию UI и сетевых операций.