Frontend Engineering Practice: The Correct Approach to HTTP Request Interception and Error Handling

“Did the API request fail? There was no prompt at all!” “The backend returned 401, and I’m still clicking on the page…”

If you have encountered similar awkward situations in your project, you may need to understand the HTTP request interception and error handling mechanism in the frontend.

In modern frontend projects like Vue/React, API requests are at the core of daily development. How to elegantly manage these requests globally — including adding tokens uniformly, displaying error pop-ups, automatically redirecting to login, and capturing network exceptions — is crucial for the robustness of the project.

This article will explain how to <span><span>axios</span></span> can be used to intercept requests and responses, centrally handle exceptions, and enhance user experience and development efficiency.

šŸ“¦ What are Request Interception and Response Interception?

When using <span><span>axios</span></span>, interceptors can be used to uniformly add or process each request/response, similar to applying middleware to the API.

// Request interceptor
axios.interceptors.request.use(config => {
    // Add token before sending the request
    config.headers.Authorization = getToken();
    return config;
}, error => Promise.reject(error));

// Response interceptor
axios.interceptors.response.use(response => {
    // Preprocess successful response data
    return response.data;
}, error => {
    // Unified error handling
    handleError(error);
    return Promise.reject(error);
});

✨ Request Interception: Unified Handling of Pre-Request Operations

Request interception is typically used for:

Purpose Example
Adding authentication token Include <span><span>Authorization</span></span> request header
Adding a unified prefix or baseUrl Adapting to proxies or environments
Initiating loading state Displaying page loading animation
Including traceId / sessionId Backend log positioning, process tracking

Example code:

axios.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    if (token) {
        config.headers['Authorization'] = `Bearer ${token}`;
    }
    // Other headers can be added
    config.headers['X-Request-Id'] = generateUUID();
    return config;
}, error => {
    return Promise.reject(error);
});

⚠ Response Interception: Unified Handling of Return Results and Errors

Response interception can perform two tasks:

āœ… 1. Unified Data Format Handling

Many APIs return formats like:

{"code":0,"data":{...},"msg":"Success"}

This can be uniformly processed as:

axios.interceptors.response.use(response => {
    const { code, data, msg } = response.data;
    if (code === 0) {
        return data;
    } else {
        ElMessage.error(msg || 'Request failed');
        return Promise.reject(new Error(msg));
    }
});

Thus, components can directly use:

const res = await api.getUser(); // Returns data

āŒ 2. Error Handling (401, 500, Network Disconnection, etc.)

axios.interceptors.response.use(
    res => res,
    error => {
        const status = error.response?.status;
        if (status === 401) {
            ElMessage.warning('Login has expired, please log in again');
            router.push('/login');
        } else if (status === 500) {
            ElMessage.error('The server is having issues, please try again later');
        } else if (!error.response) {
            ElMessage.error('Network exception, please check your network connection');
        } else {
            ElMessage.error(error.response.data?.msg || 'Request failed');
        }
        return Promise.reject(error);
    }
);

šŸ›  Recommended Strategies for Practical Implementation

In actual projects, we recommend organizing HTTP interception and error handling logic as follows:

āœ… Modularized Interceptor Registration

// http.ts
import axios from 'axios';
import { ElMessage } from 'element-plus';

const instance = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL,
    timeout: 10000,
});

// Request interceptor
instance.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    if (token) config.headers['Authorization'] = `Bearer ${token}`;
    return config;
});

// Response interceptor
instance.interceptors.response.use(
    res => {
        const { code, data, msg } = res.data;
        if (code === 0) return data;
        ElMessage.error(msg || 'Request failed');
        return Promise.reject(new Error(msg));
    },
    error => {
        const status = error.response?.status;
        if (status === 401) {
            ElMessage.warning('Login expired, please log in again');
            location.href = '/login';
        } else {
            ElMessage.error('Network error or service exception');
        }
        return Promise.reject(error);
    }
);

export default instance;

āœ… API Call Example

// api/user.ts
import request from '@/utils/http';

export function getUserInfo() {
    return request.get('/user/info');
}

šŸ“Œ Common Error Scenario Handling Suggestions

Error Type Recommended Action
401 Unauthorized Clear token, redirect to login page
403 Insufficient Permissions Show prompt, no redirection
404 API Not Found Prompt and report error log
500 Backend Exception Popup prompt, allow user to retry
Network Timeout / Disconnection Prompt network issues, optional loading fallback
code !== 0 Prompt user according to backend-defined rules

šŸŽÆ Summary

  • āœ… Use request interceptors to uniformly add tokens and traceIds;
  • āœ… Use response interceptors to uniformly handle code checks and exception prompts;
  • āœ… Error handling should be clear and provide feedback, avoiding “black box usage” for users;
  • āœ… It is recommended to modularize interceptor logic to avoid duplicate code;
  • āœ… The larger the project, the more significant the benefits of unified error handling.

You can further introduce:

  • šŸ” <span><span>Sentry</span></span> and other error monitoring tools to log exceptions
  • ā± Unified handling of loading states (e.g., in conjunction with a global loading manager)
  • 🚄 Request cancellation features (e.g., interrupting unnecessary requests during route changes)

How do you handle HTTP requests and errors in your project? Feel free to share your experiences in the comments!

Leave a Comment