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.