JAVASCRIPT

Centralized API Error Handling with Axios Interceptors in Vue 3

Implement a robust global error handling strategy for all API requests in your Vue 3 app using Axios interceptors, enabling consistent error feedback and debugging.

// utils/axiosInstance.js
import axios from 'axios';

const axiosInstance = axios.create({
  baseURL: 'https://api.example.com/',
  timeout: 10000, // 10 seconds
  headers: {
    'Content-Type': 'application/json',
  },
});

// Request Interceptor: Add auth token or other headers
axiosInstance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    // You could also add a loading spinner here
    // store.dispatch('setLoading', true);
    return config;
  },
  (error) => {
    // Handle request errors (e.g., network issues before sending)
    console.error('Request Error:', error);
    return Promise.reject(error);
  }
);

// Response Interceptor: Handle global errors (e.g., 401, 500)
axiosInstance.interceptors.response.use(
  (response) => {
    // store.dispatch('setLoading', false);
    return response;
  },
  (error) => {
    // store.dispatch('setLoading', false);

    const { response } = error;
    if (response) {
      console.error('API Error Status:', response.status);
      console.error('API Error Data:', response.data);

      switch (response.status) {
        case 401:
          console.warn('Unauthorized: Redirecting to login or refreshing token...');
          // Example: Redirect to login page
          // router.push('/login?sessionExpired=true');
          break;
        case 403:
          console.warn('Forbidden: User does not have necessary permissions.');
          // Example: Show a notification message
          // notificationService.showError('Access Denied');
          break;
        case 404:
          console.warn('Not Found: The requested resource does not exist.');
          break;
        case 500:
          console.error('Server Error: Something went wrong on the server.');
          // Example: Log error to a monitoring service
          break;
        default:
          console.error(`Unhandled API Error: ${response.status}`);
          break;
      }
    } else if (error.request) {
      // The request was made but no response was received
      console.error('Network Error: No response from server.', error.request);
    } else {
      // Something happened in setting up the request that triggered an Error
      console.error('Axios config Error:', error.message);
    }

    // Crucial: Reject the promise so component-level catch blocks still work
    return Promise.reject(error);
  }
);

export default axiosInstance;

// MyComponent.vue (How to use it)
<template>
  <div>
    <button @click="fetchData">Fetch Data</button>
    <p v-if="data">Data: {{ data }}</p>
    <p v-if="error" style="color: red;">Error: {{ error.message }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axiosInstance from '@/utils/axiosInstance'; // Adjust path as needed

const data = ref(null);
const error = ref(null);

const fetchData = async () => {
  data.value = null;
  error.value = null;
  try {
    const response = await axiosInstance.get('/some-endpoint'); // Use the configured instance
    data.value = response.data;
  } catch (err) {
    // This catch block will only be reached if the interceptor re-rejects the promise.
    // Global handling already occurred, but you can do component-specific handling here.
    error.value = err;
    console.log('Component caught error, global handler already ran.');
  }
};
</script>
How it works: This snippet demonstrates how to set up global API error handling in a Vue 3 application using Axios interceptors. It creates a custom Axios instance and attaches `request` and `response` interceptors. The `request` interceptor can add headers like an authorization token. The `response` interceptor centrally catches HTTP errors (e.g., 401, 404, 500), allows for consolidated logging, displays user notifications, or triggers actions like re-authentication, preventing repetitive error handling logic in every component. By rejecting the promise, errors still propagate to component-level `catch` blocks for specific handling.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs