Axios面试常见问题详解

发布于:2025-06-16 ⋅ 阅读:(18) ⋅ 点赞:(0)

axios面试常问题目及其详解

以下是前端面试中关于 Axios 的常见问题及详细解答,涵盖核心原理、实战场景和进阶优化,帮助你在面试中清晰展示技术深度。


1. Axios 是什么?它与原生 Fetch API 有何区别?

回答要点:
  • Axios 是什么:
    Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。它封装了底层的 XMLHttpRequest(浏览器)和 http 模块(Node.js),提供了更简洁的 API 和丰富的功能(如拦截器、自动转换 JSON 数据等)。
    在这里插入图片描述
面试场景:

“在项目中为什么选择 Axios 而不是 Fetch?”
回答:
“Axios 的拦截器功能可以统一处理认证(如自动附加 Token)、错误提示(如 401 跳转登录页)和请求日志,减少重复代码。此外,Axios 自动转换 JSON 数据,避免了手动调用 response.json() 的繁琐操作,尤其在需要兼容 IE 时,Axios 的 Polyfill 支持更友好。”


2. Axios 的拦截器如何工作?实际项目中如何使用?

回答要点:
  • 拦截器类型:
    • 请求拦截器:在请求发送前执行(如附加 Token、修改请求头)。
    • 响应拦截器:在响应返回后执行(如统一处理错误、数据格式化)。
  • 代码示例:
// 请求拦截器:附加 Token
axiosInstance.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  if (token) config.headers.Authorization = `Bearer ${token}`;
  return config;
});

// 响应拦截器:统一处理错误
axiosInstance.interceptors.response.use(
  response => response.data, // 直接返回数据部分
  error => {
    if (error.response?.status === 401) {
      // 跳转登录页
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);
  • 实际场景:
    • 认证管理:自动附加 Token,避免每个请求手动添加。
    • 错误兜底:统一处理 4xx/5xx 错误,减少组件内的重复代码。
    • 数据格式化:后端返回数据包裹在 { code, data, message } 中,拦截器可提取 data 部分。
面试场景:

“如何通过拦截器实现用户登录状态的自动管理?”
回答:
“在请求拦截器中检查本地存储的 Token,并附加到请求头。在响应拦截器中,如果遇到 401 错误(Token 过期),自动清除本地 Token 并跳转登录页,无需在每个 API 调用中重复判断。”


3. 如何用 Axios 取消重复或过时的请求?

回答要点:
  • 取消方式:
    • CancelToken(旧版):
const source = axios.CancelToken.source();
axios.get('/api/data', { cancelToken: source.token });
// 取消请求
source.cancel('用户取消操作');
2.  AbortController(推荐):
const controller = new AbortController();
axios.get('/api/data', { signal: controller.signal });
// 取消请求
controller.abort('请求超时');
  • 防重复提交:
    通过缓存请求标识(如 URL + 参数 + 时间戳),在拦截器中拦截短时间内重复的请求。
    示例:
const pendingRequests = new Map();
axiosInstance.interceptors.request.use(config => {
  const requestKey = `${config.url}-${JSON.stringify(config.params)}`;
  if (pendingRequests.has(requestKey)) {
    pendingRequests.get(requestKey).abort(); // 取消前一个相同请求
  }
  const controller = new AbortController();
  config.signal = controller.signal;
  pendingRequests.set(requestKey, controller);
  return config;
});
axiosInstance.interceptors.response.use(response => {
  const requestKey = `${response.config.url}-${JSON.stringify(response.config.params)}`;
  pendingRequests.delete(requestKey); // 请求完成,移除缓存
  return response;
});
面试场景:

“用户快速点击按钮多次提交表单,如何避免重复请求?”
回答:
“在请求拦截器中生成请求的唯一标识(如 URL + 参数),并用 Map 缓存正在进行的请求。如果相同请求已存在,则调用 AbortController.abort() 取消前一个请求,确保只有最后一次请求被执行。”


4. Axios 如何处理跨域问题?CORS 和 JSONP 的区别?

回答要点:
  • Axios 跨域解决方案:

    • CORS(推荐):后端设置响应头(如 Access-Control-Allow-Origin),浏览器允许跨域请求。
      • 简单请求:直接发送请求。
      • 预检请求(Preflight):先发 OPTIONS 请求,后端需支持 OPTIONS 方法并返回允许的跨域头。
    • 代理服务器:开发时通过 Webpack DevServer 或 Nginx 反向代理,将请求转发到目标服务器(前端代码无跨域问题)。
  • CORS vs JSONP:
    |对比项|CORS|JSONP|
    |原理|基于 HTTP 头部的跨域控制|利用

面试场景:

“项目遇到跨域问题,如何通过 Axios 解决?”
回答:
“如果是开发环境,通过 Webpack DevServer 配置代理,将 API 请求转发到后端服务器。生产环境则让后端配置 CORS 头,允许前端域名访问。JSONP 仅作为备选方案,因仅支持 GET 且安全性较低。”


5. 如何实现 Axios 的请求重试机制?

回答要点:
  • 实现思路:
    在响应拦截器中捕获网络错误或特定状态码(如 5xx),通过递归或定时器重试请求。
    代码示例:
axiosInstance.interceptors.response.use(null, error => {
  if (error.code === 'ECONNABORTED' || !error.response) {
    // 网络超时或断开,重试
    return retryRequest(error.config);
  }
  return Promise.reject(error);
});

function retryRequest(config, retryCount = 3) {
  if (retryCount <= 0) return Promise.reject('重试次数耗尽');
  config.__retryCount = config.__retryCount || 0;
  config.__retryCount += 1;
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(axiosInstance(config));
    }, 1000 * config.__retryCount); // 指数退避
  }).then(response => response)
    .catch(err => retryRequest(config, retryCount - 1));
}
  • 适用场景:
    • 网络不稳定导致请求失败。
    • 后端服务临时不可用(如 502/504 错误)。
面试场景:

“如何优化弱网环境下的请求成功率?”
回答:
“通过拦截器实现请求重试机制,结合指数退避策略(如首次重试延迟 1s,第二次 2s),避免短时间内频繁重试加重服务器负担。同时限制最大重试次数(如 3 次),防止无限重试。”


6. Axios 的全局配置和实例化配置有何区别?

回答要点:
  • 全局默认配置:
    通过 axios.defaults 设置,影响所有请求(不推荐,易产生冲突)。
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.timeout = 5000;
  • 实例化配置:
    创建独立的 Axios 实例,每个实例可单独配置,避免全局污染。
const apiInstance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
});
apiInstance.interceptors.request.use(...); // 实例级拦截器
  • 优先级:
    实例配置 > 全局配置 > 请求配置(axios.get(url, { timeout: 10000 }) 可覆盖实例配置)。
面试场景:

“多个模块需要调用不同后端 API,如何管理 Axios 配置?”
回答:
“为每个模块创建独立的 Axios 实例,分别配置 baseURL 和拦截器。例如,用户模块实例指向 /user 接口,支付模块实例指向 /pay 接口,避免全局配置混乱。”


总结

在面试中回答 Axios 相关问题时,需结合 原理、实战场景 和 代码实现,突出以下能力:

  1. 底层机制的理解(如拦截器、取消请求)。
  2. 解决实际问题的经验(如跨域、重复提交、错误处理)。
  3. 代码设计的规范性(如实例化配置、重试机制)。
    通过清晰的逻辑和具体的例子,可以充分展示你对 Axios 的掌握程度和工程化思维。


下面是一些关于 Axios 在前端面试中常见的问题及其详解,涵盖了基础用法、配置、拦截器、错误处理等方面,适合前端开发岗位:


✅ 基本 Axios 面试题目详解

1. 什么是 Axios?它有哪些特点?

答案:
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。
特点:

  • 支持 Promise API
  • 支持请求/响应拦截器
  • 请求和响应数据转换
  • 自动转换 JSON 数据
  • 防止 CSRF/XSRF 攻击
  • 客户端支持取消请求(通过 CancelToken)
  • 支持并发请求(axios.all()

2. Axios 和 Fetch 的区别?

特点 Axios Fetch
默认数据格式 JSON 自动解析 需要手动解析 .json()
请求拦截器 支持 不支持
响应拦截器 支持 不支持
超时设置 支持 需手动实现
请求取消 支持 CancelToken 需使用 AbortController
浏览器兼容性 更好 较新浏览器支持更好

3. 如何配置全局默认值?

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.timeout = 5000;
axios.defaults.headers.common['Authorization'] = 'Bearer token';

4. Axios 如何设置请求拦截器和响应拦截器?

// 请求拦截器
axios.interceptors.request.use(config => {
  // 可添加 token 等操作
  config.headers['X-Custom-Header'] = 'value';
  return config;
}, error => Promise.reject(error));

// 响应拦截器
axios.interceptors.response.use(response => {
  return response.data; // 直接返回数据部分
}, error => {
  // 错误处理
  if (error.response) {
    // 服务端返回错误
    console.error('Error:', error.response.status);
  } else if (error.request) {
    // 没有响应
    console.error('No response received');
  } else {
    console.error('Request setup error:', error.message);
  }
  return Promise.reject(error);
});

5. Axios 如何发送 GET、POST 请求?

// GET 请求
axios.get('/user', { params: { id: 1 } });

// POST 请求
axios.post('/user', { name: 'John', age: 25 });

6. 如何处理请求错误?

axios.get('/user/123')
  .then(response => console.log(response))
  .catch(error => {
    if (error.response) {
      console.log('Status:', error.response.status);
      console.log('Data:', error.response.data);
    } else if (error.request) {
      console.log('No response:', error.request);
    } else {
      console.log('Error:', error.message);
    }
  });

7. 如何取消 Axios 请求?

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('/user', {
  cancelToken: source.token
}).catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  }
});

source.cancel('Request canceled by user');

8. 如何使用 Axios 并发请求?

axios.all([
  axios.get('/user'),
  axios.get('/profile')
]).then(axios.spread((userRes, profileRes) => {
  console.log(userRes.data);
  console.log(profileRes.data);
}));

9. Axios 如何上传文件?

const formData = new FormData();
formData.append('file', fileInput.files[0]);

axios.post('/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' }
});

10. 如何在 Axios 中设置超时时间?

axios.get('/slow-api', {
  timeout: 3000 // 毫秒
});

✅ 高阶 Axios 面试题目详解


1. Axios 请求流程底层是如何工作的?

回答要点:
Axios 封装了 XMLHttpRequest(浏览器端)或 http 模块(Node.js),主要流程如下:

  1. 创建 Axios 实例(配置合并)。
  2. 执行请求拦截器(通过拦截器链)。
  3. 发起请求(浏览器中通过 XMLHttpRequest)。
  4. 接收响应并执行响应拦截器。
  5. 返回 Promise。

底层通过一个责任链模式(InterceptorManager)来组织拦截器,实际调用栈如下:

dispatchRequest(config) -> xhrAdapter(config) -> new XMLHttpRequest

2. Axios 拦截器是如何实现的?是同步还是异步?

回答要点:

  • 拦截器是通过拦截器链(interceptors)维护的:

    axios.interceptors.request.use(fn1);
    axios.interceptors.response.use(fn2);
    
  • 这些拦截器会被组成一个 Promise chain 链式结构:

let chain = [dispatchRequest, undefined]; // 核心请求处理
// 前置拦截器从前往后插入
// 后置拦截器从后往前插入

// 然后通过 promise 链式调用处理请求
  • 所以拦截器是异步可控的 Promise 链调用机制

3. Axios 如何实现请求合并或去重(防止重复请求)?

回答要点:

可通过维护一个请求队列 Map 实现唯一 key:

const pendingMap = new Map();

function generateKey(config) {
  const { url, method, params, data } = config;
  return `${method}&${url}&${JSON.stringify(params)}&${JSON.stringify(data)}`;
}

function addPending(config) {
  const key = generateKey(config);
  if (!pendingMap.has(key)) {
    config.cancelToken = new axios.CancelToken(cancel => {
      pendingMap.set(key, cancel);
    });
  } else {
    // 取消已有重复请求
    pendingMap.get(key)();
  }
}

4. 如何封装 Axios 支持自动刷新 token(如 401 自动重发)?

回答要点:

  1. 在响应拦截器中捕获 401。
  2. 发起 refreshToken 请求(需要排队等待)。
  3. 更新 token 后重放之前失败的请求。

关键代码片段:

let isRefreshing = false;
let failedQueue = [];

axios.interceptors.response.use(
  res => res,
  async error => {
    const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
      if (!isRefreshing) {
        isRefreshing = true;
        const newToken = await refreshToken();
        axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;
        failedQueue.forEach(cb => cb(newToken));
        failedQueue = [];
        isRefreshing = false;
      }

      return new Promise(resolve => {
        failedQueue.push(token => {
          originalRequest.headers['Authorization'] = 'Bearer ' + token;
          resolve(axios(originalRequest));
        });
      });
    }

    return Promise.reject(error);
  }
);

5. Axios 在 Node.js 和浏览器中有何差异?

特性 浏览器端 Node.js
请求模块 XMLHttpRequest http / https
Cookie 自动携带 需手动配置
XSRF 有默认支持 需自己配置
适配器 xhrAdapter httpAdapter

Axios 使用的是 adapter 模式:defaultAdapter 会根据运行环境自动选择。


6. 如何在 Axios 中实现重试机制?

回答要点:

可以通过封装请求逻辑或使用拦截器实现简单重试逻辑:

axios.interceptors.response.use(null, async error => {
  const config = error.config;
  if (!config || config.__retryCount >= 3) return Promise.reject(error);

  config.__retryCount = config.__retryCount || 0;
  config.__retryCount += 1;

  // 延迟重试
  await new Promise(res => setTimeout(res, 1000));
  return axios(config);
});

7. Axios 源码中的 InterceptorManager 是怎么工作的?

回答要点:

它维护了一个拦截器队列(handlers 数组),每个元素都有:

{
  fulfilled: Function,
  rejected: Function
}

当执行请求时,会将所有拦截器依次插入 Promise 链中:

let chain = [...requestInterceptors, dispatchRequest, ...responseInterceptors];

通过 Promise.resolve(config).then(...) 顺序执行所有拦截器。


8. Axios 如何实现适配器 Adapter 机制?

回答要点:

const adapter = config.adapter || defaultAdapter;
return adapter(config).then(...)

Axios 默认支持两种 adapter:

  • xhrAdapter:浏览器端用 XMLHttpRequest
  • httpAdapter:Node.js 用 http.request

适配器允许我们定制不同平台下的请求方式,非常灵活。


9. Axios 如何防止 CSRF 攻击?

回答要点:

Axios 支持自动携带 CSRF Token:

axios.defaults.xsrfCookieName = 'XSRF-TOKEN';
axios.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';

如果服务端通过 Cookie 设置了 XSRF-TOKEN,Axios 会自动读取并在请求头加上 X-XSRF-TOKEN


10. Axios 是如何合并配置项的?为什么有些配置全局无法覆盖?

回答要点:

Axios 使用 utils.mergeConfig() 深度合并默认配置和实例配置,其中:

  • 一些字段采用深合并(如 headers
  • 一些字段直接覆盖(如 url, timeout

源码中的合并策略控制了不同字段的合并行为,导致有时 axios.defaults 无法覆盖实例设置。



网站公告

今日签到

点亮在社区的每一天
去签到