логотип PurpleSchool
логотип PurpleSchool

Взаимодействие с внешними API через Axios в Vue

Автор

Олег Марков

Введение

Любое современное веб-приложение так или иначе взаимодействует с внешними сервисами и API. В приложениях на Vue одним из самых стандартных способов обмена данными с backend-сервисами является библиотека Axios. Она обеспечивает удобный, гибкий и мощный интерфейс для выполнения HTTP-запросов. Если вы планируете получать, отправлять или изменять данные с помощью API, Axios станет отличным инструментом в вашем арсенале. В этой статье я покажу вам, как интегрировать Axios во Vue-проекты, разберу разные варианты запросов и дам рекомендации по обработке полученных данных.


Установка и настройка Axios во Vue

Почему именно Axios?

Axios – это популярная JavaScript-библиотека для выполнения HTTP-запросов. Она базируется на промисах (Promise), подходит как для браузера, так и для Node.js, имеет лаконичный синтаксис и хорошо документирована. Преимущества Axios по сравнению с встроенным fetch-синтаксисом:

  • Интерцепторы для перехвата и обработки запросов/ответов
  • Гибкая сериализация объектов
  • Продвинутая обработка ошибок
  • Прямая поддержка таймаутов и отмены запросов

Как установить Axios

Начнем с самого простого — установки библиотеки. Если у вас уже есть Vue-проект (например, созданный с помощью Vue CLI или Vite), достаточно выполнить команду:

npm install axios
# Или, если используется Yarn:
yarn add axios

Импорт Axios в проект

Обычно Axios импортируют непосредственно в компоненты или отдельный сервис. Посмотрите на этот пример:

// Импорт шифруем в нужном компоненте или JS-файле
import axios from 'axios'

На практике хорошим подходом считается вынос базовой конфигурации Axios в отдельный модуль. Это позволит централизованно управлять API-URL, заголовками, авторизацией и так далее.

// src/services/api.js
import axios from 'axios'

// Создаем экземпляр Axios с базовым URL
const api = axios.create({
  baseURL: 'https://api.example.com/v1'
  // Здесь можно добавить headers, timeout и прочие настройки
})

export default api

Теперь в любом компоненте достаточно импортировать этот экземпляр:

import api from '@/services/api'

Выполнение HTTP-запросов с Axios во Vue

Пример простого GET-запроса

Давайте разберём классический пример — получение списка пользователей с внешнего API.

<template>
  <div>
    <h3>Список пользователей:</h3>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>

<script>
import api from '@/services/api'

export default {
  data() {
    return {
      users: [],       // Здесь будут храниться пользователи
      loading: false,  // Для отображения загрузки
      error: ''        // Для ошибок
    }
  },
  mounted() {
    // При монтировании компонента вызывается метод
    this.fetchUsers()
  },
  methods: {
    async fetchUsers() {
      this.loading = true
      this.error = ''
      try {
        const response = await api.get('/users')  // GET-запрос к API
        this.users = response.data               // Сохраняем данные
      } catch (err) {
        this.error = 'Ошибка загрузки пользователей' // Обрабатываем ошибку
      } finally {
        this.loading = false
      }
    }
  }
}
</script>

В этом примере:

  • api.get('/users') выполняет GET-запрос. Путь указывается относительно базового URL.
  • Ответ API доступен в свойстве response.data.
  • Ошибки ловим через try/catch.

Работа с POST, PUT и DELETE

Давайте вспомним, что кроме получения данных, часто нужно их передавать или изменять.

POST — создание нового ресурса

methods: {
  async createUser(newUser) {
    try {
      const response = await api.post('/users', newUser)
      // В response.data обычно возвращается созданный пользователь
    } catch (err) {
      // Обработка ошибок
    }
  }
}
  • Второй аргумент — отправляемые данные.

PUT/PATCH — обновление ресурса

methods: {
  async updateUser(id, updatedUser) {
    try {
      await api.put(`/users/${id}`, updatedUser)
    } catch (err) {
      // Обработка ошибок
    }
  }
}

DELETE — удаление ресурса

methods: {
  async deleteUser(id) {
    try {
      await api.delete(`/users/${id}`)
    } catch (err) {
      // Обработка ошибок
    }
  }
}

Передача параметров и заголовков

URL-параметры

В Axios можно легко передать query string через параметр params. Пример — фильтрация:

async fetchUsersByRole(role) {
  try {
    const response = await api.get('/users', {
      params: { role }
    })
    this.users = response.data
  } catch (err) {
    // Обработка ошибок
  }
}

Кастомные заголовки

Добавим авторизационный токен:

async fetchSecureData() {
  try {
    const response = await api.get('/secure-data', {
      headers: {
        Authorization: `Bearer ${this.token}`
      }
    })
    // Используем response.data
  } catch (err) {
    // Обработка ошибок
  }
}

Универсальная обработка ошибок

Axios всегда выбрасывает ошибку при статусах ответа, отличных от успешных (2xx). Важно учитывать это в вашем коде. Для глубокого анализа можно смотреть объект error:

try {
  await api.get('/some-endpoint')
} catch (err) {
  if (err.response) {
    // Сервер вернул ответ с ошибочным статусом
    console.log('Ошибка сервера', err.response.status, err.response.data)
  } else if (err.request) {
    // Запрос был отправлен, но ответ не получен
    console.log('Нет ответа', err.request)
  } else {
    // Какая-то другая ошибка (например, синтаксис)
    console.log('Ошибка', err.message)
  }
}

Организация архитектуры работы с API

Вынесение логики взаимодействия с API в сервисы

Хорошая практика — не помещать логику работы с API прямо в компоненты, а выносить её в отдельные сервисные модули. Это улучшает читаемость кода, повторное использование и тестируемость.

// src/services/userService.js
import api from '@/services/api'

export default {
  async getUsers(params) {
    return api.get('/users', { params })
  },
  async createUser(payload) {
    return api.post('/users', payload)
  },
  // Другие методы
}

В компоненте:

import userService from '@/services/userService'

methods: {
  async loadUsers() {
    try {
      const response = await userService.getUsers({ role: 'admin' })
      this.users = response.data
    } catch (err) {
      // Обработка ошибок
    }
  }
}

Использование Axios-интерцепторов

Интерцепторы (interceptors) — это очень полезная особенность Axios, позволяющая централизованно обрабатывать запросы и ответы: например, автоматически добавлять токены, логировать, перехватывать 401-ошибки и обновлять токен доступа (refresh-token flow).

Пример добавления токена к каждому запросу

// src/services/api.js
import axios from 'axios'

const api = axios.create({
  baseURL: 'https://api.example.com/v1'
})

// Интерцептор для автоматического добавления токена
api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => Promise.reject(error)
)

export default api

Перехватчик ошибок

api.interceptors.response.use(
  (response) => response,
  (error) => {
    // Если 401 – возможно, требуется выйти из аккаунта или обновить токен
    if (error.response && error.response.status === 401) {
      // Логика выхода или обновления токена
    }
    return Promise.reject(error)
  }
)

Реактивность и асинхронные запросы

Рекомендации по работе с асинхронностью и хранением данных

Vue отлично работает с реактивными данными. После получения ответа API данные, сохранённые в state (data или store), автоматически обновляют представление (view). Действия накладываем через методы или функции.

  • Лучше помещать вызовы API во хуки жизненного цикла (например, mounted или created), а не в конструкторы компонентов.
  • Для сложных приложений используйте глобальное хранилище состояния (Vuex или Pinia).

Пример интеграции с Pinia

Pinia — современный state-менеджер для Vue. Работа с Axios тут аналогична:

// stores/userStore.js
import { defineStore } from 'pinia'
import userService from '@/services/userService'

export const useUserStore = defineStore('user', {
  state: () => ({
    users: [],
    loading: false,
    error: null
  }),
  actions: {
    async fetchUsers() {
      this.loading = true
      this.error = null
      try {
        const response = await userService.getUsers()
        this.users = response.data
      } catch (err) {
        this.error = err.response?.data?.message || 'Ошибка загрузки'
      } finally {
        this.loading = false
      }
    }
  }
})

Дополнительные возможности Axios

Тайм-ауты, отмена запросов и прогресс

Установка тайм-аута

const api = axios.create({
  baseURL: 'https://api.example.com/',
  timeout: 5000 // 5 секунд
})
  • Если сервер не ответит за 5 секунд, будет выброшена ошибка.

Как отменять запросы (Abort)

Иногда бывает необходимо отменить "зависший" запрос, например, если пользователь уходит со страницы.

const controller = new AbortController()

api.get('/users', {
  signal: controller.signal
})
// Позже в коде
controller.abort()

Слежение за прогрессом загрузки/отправки

Полезно для загрузки больших файлов.

api.post('/upload', formData, {
  onUploadProgress: (progressEvent) => {
    const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
    // Показываем пользователю прогресс
  }
})

Тестирование API-вызовов (unit-тесты)

Покажу вам подход к тестированию сервисов, использующих Axios. Обычно используется библиотека jest с моками.

// userService.test.js
import api from '@/services/api'
import userService from '@/services/userService'

// Мокаем get-запрос
jest.mock('@/services/api', () => ({
  get: jest.fn()
}))

test('getUsers вызывает api.get с параметрами', async () => {
  api.get.mockResolvedValue({ data: [{ id: 1, name: 'Ivan' }] })
  const result = await userService.getUsers()
  expect(api.get).toHaveBeenCalledWith('/users', { params: undefined })
  expect(result.data[0].name).toBe('Ivan')
})
  • Мокаем и подставляем ожидаемый результат, не обращаясь к реальному API.

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

Композиционный API (Composition API) и Axios

Vue 3 располагает новым подходом — Composition API с реэкспортируемыми функциями.

// useUsers.js
import { ref } from 'vue'
import userService from '@/services/userService'

export function useUsers() {
  const users = ref([])
  const loading = ref(false)
  const error = ref(null)

  async function fetchUsers() {
    loading.value = true
    error.value = null
    try {
      const response = await userService.getUsers()
      users.value = response.data
    } catch (err) {
      error.value = 'Ошибка загрузки'
    } finally {
      loading.value = false
    }
  }

  return { users, loading, error, fetchUsers }
}

Использование в компоненте:

<script setup>
import { onMounted } from 'vue'
import { useUsers } from '@/composables/useUsers'

const { users, loading, error, fetchUsers } = useUsers()
onMounted(fetchUsers)
</script>

Локализация и интернационализация запросов

Если вы работаете с многоязычными данными или API поддерживает локализацию, можно передавать локаль прямо в заголовках или параметрах.

api.get('/catalog', {
  headers: {
    'Accept-Language': 'ru'
  }
})
  • Это может управляться динамически, если пользователь выбирает язык в вашем приложении.

Заключение

Axios — мощный и гибкий инструмент для интеграции внешних API в проекты на Vue. Он предлагает удобный синтаксис, расширяемую конфигурацию, отличную обработку ошибок и ряд продвинутых функций. Грамотное вынесение запросов в сервисы, использование интерцепторов, управление асинхронностью и работа с Vue-хранилищами позволяют строить масштабируемые и поддерживаемые фронтенд-приложения. Следуя приведённым выше рекомендациям и шаблонам, вы легко сможете взаимодействовать с любым HTTP API наиболее эффективным способом.


Частозадаваемые технические вопросы по теме статьи и ответы на них

Как настроить базовый URL для разных окружений (dev/prod)?

Часто проекты используют разные API-адреса для разработки и продакшена. Самый удобный способ — использовать переменные окружения. В файле .env:

VUE_APP_API_URL=https://api.dev.example.com

Затем при создании экземпляра Axios:

const api = axios.create({
  baseURL: process.env.VUE_APP_API_URL
})

Как отменить неактуальные API-запросы при переключении маршрута?

Создайте AbortController и передавайте его сигнал в запрос. При смене маршрута вызывайте controller.abort(), например, в хуке beforeRouteLeave или onUnmounted (Vue 3).

Как обработать ошибку сети при запросе в Axios?

Если сервер не отвечает (отключен интернет или API недоступно), Axios выбросит ошибку с пустым error.response. Для таких случаев проверяйте наличие error.response — если его нет, покажите “Нет соединения с сервером”.

Как объединять несколько запросов в один (например, Promise.all)?

Axios возвращает промисы, и вы можете использовать Promise.all():

const [res1, res2] = await Promise.all([
  api.get('/users'),
  api.get('/posts')
])

Как добавить глобальный preloader для всех запросов?

Добавьте состояние загрузки (например, с помощью Vuex/Pinia или реактивной переменной) и переключайте его через Axios-интерцепторы: до запроса ставьте в true, после — в false.


Стрелочка влевоПонимание и применение Composition API в Vue 3

Все гайды по Vue

Работа с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueОбзор популярных шаблонов и стартовых проектов на VueКак организовать страницы и маршруты в проекте на VueСоздание серверных приложений на Vue с помощью Nuxt jsРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияНастройка и сборка проектов Vue с использованием современных инструментов
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование метода map в Vue для обработки массивовОбработка пользовательского ввода в Vue.jsОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitИспользование директив и их особенности на Vue с помощью defineСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в Vue
Открыть базу знаний