【前端知识点总结】请求/响应拦截器的介绍

在现代前端应用中,与后端服务的 HTTP 通信是项目的命脉。我们频繁地发起请求、处理响应。但如果每个请求都需要手动处理通用逻辑(如添加 token、错误处理),代码将变得冗余、难以维护。这时,拦截器便应运而生,它如同我们与服务器之间的"智能关卡",赋予了我们在请求发送前和响应返回后执行自定义逻辑的强大能力。

1. 什么是拦截器?为什么需要它?

拦截器,顾名思义,是在 HTTP 请求或响应的传输过程中"拦截"它们,并在其被 then 或 catch 处理之前,执行一段特定的代码。

大多数主流 HTTP 客户端库,如 Axios,都内置了拦截器机制。它分为两种:

  1. 请求拦截器:在请求发送到服务器之前执行。
  2. 响应拦截器:在服务器返回响应,但在 Promise 的 then 或 catch 处理之前执行。

一个没有拦截器的痛点场景:

想象一下,你的应用中每个 API 请求都需要:

  1. 携带一个身份验证令牌。
  2. 显示一个全局的加载动画。
  3. 统一处理各种 HTTP 错误码(如 401 未授权、500 服务器错误)。

你的代码可能会是这样:

javascript 复制代码
// 请求 A
function fetchUserA() {
  showLoading();
  const token = localStorage.getItem('token');
  axios.get('/api/user/a', { headers: { Authorization: `Bearer ${token}` } })
    .then(response => {
      // ...处理成功逻辑
    })
    .catch(error => {
      if (error.response?.status === 401) {
        redirectToLogin();
      } else if (error.response?.status === 500) {
        showError('服务器错误');
      } else {
        showError('网络异常');
      }
    })
    .finally(() => {
      hideLoading();
    });
}

// 请求 B
function fetchUserB() {
  showLoading();
  const token = localStorage.getItem('token');
  axios.get('/api/user/b', { headers: { Authorization: `Bearer ${token}` } })
    .then(response => {
      // ...处理成功逻辑
    })
    .catch(error => {
      // ...完全相同的错误处理逻辑
    })
    .finally(() => {
      hideLoading();
    });
}

这简直是维护的灾难!代码高度重复,逻辑耦合严重。而拦截器,正是解决这类问题的"银弹"。

2. 拦截器核心应用场景

让我们看看拦截器如何优雅地解决上述问题。

场景一:请求拦截器 ------ 统一处理认证与信息

请求拦截器最常见的用途是自动添加认证信息

javascript 复制代码
// src/utils/request.js
import axios from 'axios';

const service = axios.create({ baseURL: '/api' });

// 添加请求拦截器
service.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么
    const token = localStorage.getItem('token');
    if (token) {
      // 如果 token 存在,则统一在请求头中添加 Authorization 字段
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 可以在这里添加其他通用信息,如请求ID、时间戳等
    // config.headers['X-Request-ID'] = generateUUID();

    return config; // 必须返回 config,否则请求将无法发送
  },
  (error) => {
    // 对请求错误做些什么
    console.error('Request Error:', error);
    return Promise.reject(error);
  }
);

现在,所有通过这个 service 实例发起的请求,都会自动带上 Authorization 头,业务代码无需再关心此事。

场景二:响应拦截器 ------ 统一处理响应与错误

响应拦截器是处理通用逻辑的另一个关键环节,主要用于 数据格式化错误处理

javascript 复制代码
// src/utils/request.js (接上文)

// 添加响应拦截器
service.interceptors.response.use(
  (response) => {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么,例如:直接返回我们关心的 data 部分
    const res = response.data;
    
    // 假设后端约定,所有成功响应的 code 都是 0
    if (res.code !== 0) {
      // 如果 code 不是 0,说明业务逻辑上存在错误
      showError(res.message || '业务错误');
      return Promise.reject(new Error(res.message || 'Error'));
    } else {
      // 返回真正的业务数据
      return res.data;
    }
  },
  (error) => {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 未授权,token 失效或过期
          showError('登录已过期,请重新登录');
          // 清除本地 token 并跳转到登录页
          localStorage.removeItem('token');
          redirectToLogin();
          break;
        case 403:
          showError('没有权限访问');
          break;
        case 404:
          showError('请求的资源不存在');
          break;
        case 500:
          showError('服务器内部错误');
          break;
        default:
          showError(`请求失败: ${error.response.status}`);
      }
    } else if (error.request) {
      // 请求已发出,但没有收到响应
      showError('网络连接异常,请检查网络');
    } else {
      // 在设置请求时触发了错误
      showError('请求配置错误');
    }
    
    return Promise.reject(error); // 将错误继续传递下去,方便业务层做特定处理
  }
);

经过这样的配置,我们的业务代码变得异常简洁:

javascript 复制代码
// 简洁的业务代码
import request from '@/utils/request';

export function fetchUserA() {
  return request.get('/user/a'); // 自动携带token,自动处理错误,自动返回 data
}

export function fetchUserB() {
  return request.get('/user/b');
}

3. 企业级开发中的拦截器最佳实践

在企业级项目中,拦截器的使用需要更加规范和健壮。以下是几条重要的最佳实践。

实践一:封装统一的请求模块

❗❗❗永远不要在组件中直接使用 axios!应该创建一个统一的请求模块(如 src/utils/request.js),在该模块中创建 axios 实例并配置所有拦截器。所有业务代码都应通过导入这个模块来发起请求。

这样做的好处是:

  • 统一配置:所有 baseURL、timeout、拦截器逻辑都集中在一处。
  • 易于替换:未来如果想从 Axios 迁移到 fetch 或其他库,只需修改这一个文件,而不用改动全业务代码。
  • 职责分离:将网络通信的底层逻辑与业务逻辑解耦。

实践二:Token 刷新与无感刷新

在企业应用中,Token(尤其是 JWT)有过期时间。当 Token 过期时,用户会频繁被踢下线,体验极差。拦截器可以实现 无感刷新 Token

核心流程:

  1. 响应拦截器捕获到 401 错误。
  2. 判断是否为 Token 过期(而非无效)。
  3. 如果是,则发起一个刷新 Token 的请求到后端(使用 refresh_token )。
  4. 如果刷新成功,将新的 access_token 存入本地存储,并重新发送刚才失败的请求。
  5. 如果刷新失败,则说明用户需要重新登录,引导其跳转。

关键点:

防止并发刷新:当多个请求同时返回 401 时,应确保只发送一个刷新请求。可以使用一个标志位(如 isRefreshing )和一个待处理请求队列来实现。

失败处理:刷新 Token 的请求本身也可能失败,需要有兜底逻辑(如强制登出)。

实践三:取消重复请求

在某些场景下,用户快速点击按钮可能会发起多个完全相同的请求,造成服务器压力和数据混乱。拦截器可以帮助我们取消正在进行的重复请求。

实现思路:

  1. 在请求拦截器中,为每个请求生成一个唯一的 key (如 method + url + params )。
  2. 维护一个 Map 或 Object 来存储每个 key 对应的 CancelToken 。
  3. 当新请求进来时,检查其 key 是否已存在于 Map 中。
  4. 如果存在,则取消上一次的请求,并用新的 CancelToken 覆盖它。
  5. 请求完成后(无论成功失败),从 Map 中移除该 key 。

Axios 的 CancelToken (在新版本中推荐使用 AbortController )是实现此功能的关键。

实践四:请求/响应日志与监控

在开发和生产环境中,对请求响应进行日志记录是排查问题的关键。

  • 开发环境:可以在拦截器中 console.log 请求的 config 和响应的 data ,方便调试。
  • 生产环境:可以将请求失败、API 耗时过长等关键信息上报到监控系统(如 Sentry、Fundebug),帮助团队快速发现和定位线上问题。
javascript 复制代码
 // 在响应拦截器中添加日志
service.interceptors.response.use(
  response => {
    // ...其他逻辑
    const duration = Date.now() - response.config.metadata.startTime;
    if (duration > 3000) { // 监控慢请求
      monitor.logSlowRequest(response.config.url, duration);
    }
    return response.data;
  },
  error => {
    // ...错误处理
    monitor.logApiError(error); // 上报 API 错误
    return Promise.reject(error);
  }
);

// 在请求拦截器中记录开始时间
service.interceptors.request.use(config => {
  config.metadata = { startTime: Date.now() };
  return config;
});

4. 🪄手把手教你写响应拦截器

我将用最直白的话,手把手教你如何让根据不同情况写响应拦截器

想象一下,响应拦截器 就像一个"快递签收检查员"。

  • 快递员(后端服务器)把包裹(HTTP响应)送到你家门口。
  • 检查员(响应拦截器)先帮你签收,然后打开包裹检查。

检查结果分两种:

  1. 包裹完好,东西是你想要的(成功响应):检查员把里面的宝贝(数据)直接递给你。
  2. 包裹有问题(失败响应):比如地址错了(404)、没权限(401)、或者快递公司仓库着火了(500)。检查员会告诉你具体是什么问题,并帮你处理(比如让你重新登录)。

这样,你每次收快递就不用自己费劲去检查了,检查员都帮你搞定了。我们开始吧!

第零步:准备工作

我们以最流行的 axios 库为例。首先,你的项目里需要安装它。

bash 复制代码
npm install axios
# 或者
yarn add axios

然后,在你的项目里新建一个文件,专门用来管网络请求。比如 src/utils/request.js。我们所有的拦截器都写在这里。

情况一:最简单的成功响应("检查员只递给你宝贝")

**场景:**后端返回的数据格式是 { code: 0, message: 'success', data: { ... } }。我们只关心 data 里的内容,不想每次都写 response.data.data。

**目标:**让业务代码直接拿到 data。

在 src/utils/request.js 中这样写:

javascript 复制代码
// 1. 导入 axios
import axios from 'axios';

// 2. 创建一个 axios 实例(就像创建一个专属的快递员)
const service = axios.create({
  baseURL: 'https://api.example.com', // 你的API基地址
  timeout: 5000 // 请求超时时间
});

// 3. 添加响应拦截器(我们的"检查员"上岗了!)
service.interceptors.response.use(
  // ✅ 这个函数处理成功的情况 (HTTP状态码 2xx)
  (response) => {
    // response 是整个响应对象,里面包含了 headers, status, data 等
    // 我们只需要把 response.data 里的 data 字段返回出去
    return response.data.data; 
  },
  
  // ❌ 这个函数处理失败的情况 (HTTP状态码非 2xx)
  (error) => {
    // 现在先简单地把错误抛出去,我们后面再详细说
    return Promise.reject(error); 
  }
);

// 4. 把这个配置好的 service 导出,给其他页面用
export default service;

怎么用?

在你的业务文件里(比如 src/api/user.js):

javascript 复制代码
import request from '@/utils/request'; // 引入我们配置好的"快递员"

// 获取用户信息
export function getUserInfo(userId) {
  return request.get(`/users/${userId}`);
}

// 在组件里调用
// getUserInfo(123).then(data => {
//   console.log(data); // 这里拿到的直接就是 { name: '张三', age: 25 },而不是 { code: 0, data: { name: '张三', age: 25 } }
// })

看,是不是清爽多了?这就是拦截器的第一个威力:数据精简

情况二:处理业务逻辑错误("检查员告诉你快递里的东西不对")

**场景:**后端返回的数据格式是 { code: 0, message: 'success', data: ... }。当 code 不是 0 时,表示业务逻辑有问题,比如"用户名或密码错误"(code: 1001)。

**目标:**当 code 不为 0 时,弹窗提示用户错误信息,并让请求失败。

修改 src/utils/request.js 中的成功处理函数:

javascript 复制代码
// ... 前面的代码不变 ...

service.interceptors.response.use(
  (response) => {
    const res = response.data;

    // 判断后端返回的业务状态码 code
    if (res.code === 0) {
      // 成功,直接返回数据
      return res.data;
    } else {
      // 失败,弹出错误提示
      // 假设你有一个全局的弹窗提示工具,比如 Element UI 的 Message
      // 或者简单的浏览器原生弹窗
      alert(res.message || '请求失败'); 
      
      // 并让 Promise 进入失败状态,这样业务代码的 .catch 就能捕获到
      return Promise.reject(new Error(res.message || 'Error'));
    }
  },
  // ... 失败处理函数不变 ...
);

怎么用?

javascript 复制代码
// 在组件里调用
getUserInfo(123).then(data => {
  // 只有 code 为 0 时,这里才会执行
  console.log('获取成功:', data);
}).catch(error => {
  // code 不为 0 时,这里会执行
  console.error('获取失败:', error.message); // 这里会打印 "用户名或密码错误"
});

现在,你的检查员不仅能递宝贝,还能帮你检查宝贝对不对,不对就马上告诉你!

情况三:处理 HTTP 错误("快递没送到,检查员告诉你原因")

**场景:**请求本身失败了,比如 401 (没权限)、404 (地址不存在)、500 (服务器崩了)。

**目标:**针对不同的 HTTP 错误,给用户不同的友好提示。

修改 src/utils/request.js 中的失败处理函数:

javascript 复制代码
// ... 前面的代码不变 ...

service.interceptors.response.use(
  // ... 成功处理函数不变 ...
  (error) => {
    // error.response 包含了服务器返回的详细信息
    if (error.response) {
      // 根据不同的状态码做不同的事
      switch (error.response.status) {
        case 401:
          alert('你没权限,请先登录!');
          // 这里可以加一个跳转到登录页的逻辑
          // window.location.href = '/login';
          break;
        case 403:
          alert('禁止访问!');
          break;
        case 404:
          alert('请求的资源不存在!');
          break;
        case 500:
          alert('服务器出错了,请稍后再试!');
          break;
        default:
          alert(`请求失败,错误码: ${error.response.status}`);
      }
    } else if (error.request) {
      // 请求发了,但没收到响应(比如网络断了)
      alert('网络连接异常,请检查你的网络!');
    } else {
      // 请求配置出错了
      alert('请求配置错误!');
    }
    
    // 最后,一定要把错误返回,让业务代码知道请求失败了
    return Promise.reject(error);
  }
);

// ... 后面的代码不变 ...

现在,你的"检查员"已经非常全能了!无论是包裹里的东西有问题,还是快递路上出了意外,他都能妥善处理并给你反馈。

情况四:终极挑战 - Token 过期自动刷新("检查员帮你偷偷换新钥匙")

**场景:**用户登录后会有一个 token(钥匙),但有时效性。过期后,所有请求都会返回 401。我们不能让用户重新登录,而是要偷偷用 refresh_token 换个新的 token,然后重新发送刚才失败的请求,用户对此无感知。

**目标:**实现无感刷新 Token。

这个稍微复杂一点,我们需要在拦截器外面加一些辅助变量。

修改 src/utils/request.js:

javascript 复制代码
import axios from 'axios';
import { refreshTokenAPI } from '@/api/auth'; // 假设你有一个刷新 token 的接口

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

let isRefreshing = false; // 标记是否正在刷新 token
let failedQueue = []; // 存储因为 token 过期而失败的请求

// 处理失败队列的函数
const processQueue = (error, token = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });
  failedQueue = [];
};

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // ... 和之前一样,处理业务逻辑错误 ...
    const res = response.data;
    if (res.code === 0) {
      return res.data;
    } else {
      return Promise.reject(new Error(res.message || 'Error'));
    }
  },
  async (error) => {
    const originalRequest = error.config;

    // 如果是 401 错误,并且不是刷新 token 的请求,并且没有重试过
    if (error.response.status === 401 && !originalRequest._retry && !originalRequest.url.includes('/refresh')) {
      
      if (isRefreshing) {
        // 如果正在刷新,就把当前请求加入失败队列
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        }).then(token => {
          // 刷新成功后,为原请求设置新的 token
          originalRequest.headers.Authorization = `Bearer ${token}`;
          return service(originalRequest); // 重新发送原请求
        }).catch(err => {
          return Promise.reject(err);
        });
      }

      originalRequest._retry = true; // 标记这个请求已经重试过一次了
      isRefreshing = true; // 标记正在刷新 token

      try {
        // 调用刷新 token 的接口
        const res = await refreshTokenAPI();
        const newToken = res.token;
        
        // 把新 token 存起来
        localStorage.setItem('token', newToken);

        // 为原请求设置新的 token
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        
        // 处理队列中的请求
        processQueue(null, newToken);
        
        // 重新发送原请求
        return service(originalRequest);

      } catch (refreshError) {
        // 刷新 token 失败,比如 refresh_token 也过期了
        processQueue(refreshError, null);
        localStorage.removeItem('token');
        alert('登录已过期,请重新登录');
        // window.location.href = '/login';
        return Promise.reject(refreshError);
      } finally {
        isRefreshing = false; // 无论成功失败,都结束刷新状态
      }
    }

    // 其他非 401 错误,照常处理
    // ... (可以复制情况三的错误处理逻辑) ...
    return Promise.reject(error);
  }
);

export default service;

这段代码的逻辑是:

(1) 拦截到 401 错误。

(2) 检查是否已经在刷新 token( isRefreshing )。

  • 如果正在刷新:就把这个请求先放进一个队列( failedQueue )里等着。
  • 如果没在刷新:
    • 把 isRefreshing 设为 true ,并开始调用刷新 token 的接口。
    • 如果刷新成功,拿到新 token,给队列里所有等待的请求都换上新 token 并重新发送。
    • 如果刷新失败,那就没办法了,清空 token,让用户去登录页。
    • 最后,把 isRefreshing 改回 false 。

总结:响应拦截器的各种写法。

情况一:帮你精简数据,让代码更优雅。

情况二:帮你处理业务错误,提示更友好。

情况三:帮你处理 HTTP 错误,应用更健壮。

情况四:帮你实现无感刷新,用户体验更丝滑。

5. 🪄手把手教你写请求拦截器

我将用最直白的话,手把手教你如何让根据不同情况写请求拦截器

想象一下,请求拦截器 就像一个"快递打包员"。

  • 你(业务代码)准备要寄一个包裹(发起请求)。
  • 在快递员(浏览器)来取件之前,打包员(请求拦截器)会先帮你检查包裹。

他会做一些标准操作,比如:

  1. 给所有包裹贴上统一的发货单(添加 baseURL)。
  2. 给每个包裹盖上你的专属印章(添加 Token)。
  3. 用统一的包装纸(转换数据格式)把东西包起来。

这样,你每次寄东西就不用自己费心去做这些重复的准备工作了,打包员都帮你搞定了。我们开始吧!

第零步:准备工作

我们依然以最流行的 axios 库为例,并在上一次创建的src/utils/request.js 文件里添加请求拦截器。

javascript 复制代码
// src/utils/request.js
import axios from 'axios';

const service = axios.create({
  baseURL: 'https://api.example.com', // 你的API基地址
  timeout: 5000
});

// 👇 我们将要在这里添加请求拦截器 👇

// 👆 我们将要在这里添加响应拦截器 👆

export default service;

情况一:最常见的需求 - 统一添加身份认证 Token

**场景:**用户登录后,服务器会给他一个 token(类似一张临时身份证)。之后,用户每次请求数据,都必须带上这个 token,否则服务器会认为他是非法用户。

目标: 在每个请求的 HTTP Header 里自动加上 Authorization: Bearer <token>,不用每次都手动写。

在 src/utils/request.js 中这样写:

javascript 复制代码
// ... 前面的代码不变 ...

// ✅ 添加请求拦截器(我们的"打包员"上岗了!)
service.interceptors.request.use(
  // 这个函数在请求发送前执行
  (config) => {
    // config 是本次请求的配置对象,包含了 url, method, headers 等信息
    
    // 1. 从本地存储(比如 localStorage)里获取 token
    const token = localStorage.getItem('token');

    // 2. 如果 token 存在,就把它添加到请求头的 Authorization 字段中
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // 3. 一定要返回 config,否则请求就发不出去了!
    return config;
  },

  // 这个函数在请求发送出错时执行(非常少见)
  (error) => {
    console.error('请求拦截器出错:', error);
    return Promise.reject(error);
  }
);

// ... 后面的响应拦截器代码不变 ...

怎么用?

在你的业务代码里,你完全不需要关心 token 的事:

javascript 复制代码
import request from '@/utils/request';

// 获取用户信息
export function getUserInfo(userId) {
  // 打包员会自动在请求头里加上 Authorization
  return request.get(`/users/${userId}`);
}

这就是请求拦截器最核心、最常用的功能:统一注入认证信息

情况二:处理 POST/PUT 请求的数据格式

场景: 大多数后端接口期望接收的数据格式是JSON 字符串。但有时我们可能习惯直接传入一个 JavaScript 对象。

**目标:**确保所有 POST、PUT、PATCH 请求发送的数据都是 JSON 格式。

修改 src/utils/request.js 中的请求拦截器:

javascript 复制代码
// ... 前面的代码不变 ...

service.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // ✅ 新增逻辑:处理请求数据
    // 判断请求方法,如果是 POST, PUT, PATCH
    if (['post', 'put', 'patch'].includes(config.method)) {
      // 并且如果 data 是一个对象,就把它转换成 JSON 字符串
      // (其实 axios 大部分时候会自动做,但手动控制更保险)
      if (config.data && typeof config.data === 'object') {
        config.data = JSON.stringify(config.data);
      }
    }

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// ... 后面的代码不变 ...

怎么用?

现在你可以直接传对象,拦截器会帮你搞定转换:

javascript 复制代码
import request from '@/utils/request';

// 创建新用户
export function createUser(userData) {
  // userData 是一个对象 { name: '张三', age: 25 }
  // 打包员会自动把它变成 '{"name":"张三","age":25}' 再发出去
  return request.post('/users', userData);
}

情况三:为每个请求添加唯一标识

**场景:**在复杂的应用中,为了方便排查问题,我们希望每个请求都有一个独一无二的 ID,这样当后端报错时,可以根据这个 ID 快速定位到是前端的哪一次请求出了问题。

目标: 为每个请求自动生成一个唯一的 X-Request-ID 并添加到请求头中。

修改 src/utils/request.js 中的请求拦截器:

javascript 复制代码
// ... 前面的代码不变 ...

// 先写一个生成唯一ID的简单函数
function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    const r = (Math.random() * 16) | 0,
      v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

service.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // ✅ 新增逻辑:添加唯一请求ID
    config.headers['X-Request-ID'] = generateUUID();

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// ... 后面的代码不变 ...

现在,你发出去的每一个请求都会带有一个独特的 ID,方便你在日志系统和后端进行追踪。

情况四:在开发环境打印请求信息

**场景:**在本地开发时,我们经常需要查看请求的详细信息(URL、参数、Header等)来调试。但在生产环境,这些信息不应该打印出来,以免泄露信息或影响性能。

**目标:**只在开发环境下,在控制台打印出请求的配置。

修改 src/utils/request.js 中的请求拦截器:

javascript 复制代码
// ... 前面的代码不变 ...

service.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // ✅ 新增逻辑:开发环境打印日志
    // process.env.NODE_ENV 是 webpack/vite 等工具提供的环境变量
    if (process.env.NODE_ENV === 'development') {
      console.log('🚀 发送请求:', {
        url: config.url,
        method: config.method,
        params: config.params,
        data: config.data,
      });
    }

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// ... 后面的代码不变 ...

这样,你在本地开发时,控制台会清晰地打印出每个请求的细节,非常方便调试。当代码部署到线上服务器后, process.env.NODE_ENV 会变成 'production' ,这段日志代码就不会执行了。

总结

以上即可掌握了请求拦截器的各种实用技巧。

情况一:自动加 Token ,解决认证问题。

情况二:统一数据格式,避免后端报错。

情况三:添加请求 ID,方便问题追踪。

情况四:开发环境打印日志,提升调试效率。

6. 总结

拦截器是前端 HTTP 客户端库提供的一个强大而灵活的机制,它让我们能够以一种非侵入式的方式,在请求生命周期的关键节点注入通用逻辑。

通过合理运用拦截器,我们可以:

  • 提升代码复用性:将认证、错误处理等通用逻辑抽离,避免重复代码。
  • 增强代码健壮性:统一处理边界情况,如 Token 刷新、网络错误。
  • 优化用户体验:实现无感刷新、取消重复请求,让应用更流畅。
  • 简化业务逻辑:让开发者更专注于业务本身,而非底层通信细节。

掌握拦截器,是从"会用"一个框架到"用好"一个框架的重要进阶。在企业级开发中,一套设计良好的拦截器方案,是构建高质量、高可维护性前端应用的坚实基石。

相关推荐
Y‍waiX‍‍‮‪‎⁠‌‫‎‌‫‬2 小时前
【npm】从零到一基于Vite+vue3制作自己的Vue3项目基础的npm包并发布npm
前端·npm·node.js
专注VB编程开发20年2 小时前
vb.net宿主程序通过统一接口直接调用,命名空间要一致
服务器·前端·.net
2503_928411562 小时前
12.18 中后台项目-权限管理
前端·javascript·数据库
Y‍waiX‍‍‮‪‎⁠‌‫‎‌‫‬2 小时前
NRM-NPM的镜像源管理工具使用方法
前端·npm·node.js
未来之窗软件服务7 小时前
一体化系统(九)智慧社区综合报表——东方仙盟练气期
大数据·前端·仙盟创梦ide·东方仙盟·东方仙盟一体化
陈天伟教授10 小时前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
信看11 小时前
NMEA-GNSS-RTK 定位html小工具
前端·javascript·html
Tony Bai11 小时前
【API 设计之道】04 字段掩码模式:让前端决定后端返回什么
前端