MST

星途 面试题库

面试题:Vue基于Composition API封装网络请求函数的复杂场景应用

在一个大型Vue项目中,需要基于Composition API封装网络请求函数,要求支持并发请求控制(例如最多同时发送3个请求)、请求重试机制(失败后重试3次,每次重试间隔递增)以及全局的请求和响应拦截器。请详细阐述实现方案,并给出核心代码示例。
15.7万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

实现方案

  1. 并发请求控制
    • 使用队列来存储待发送的请求。
    • 维护一个计数器,记录当前正在执行的请求数量。
    • 当正在执行的请求数量小于最大并发数时,从队列中取出请求执行。
    • 当请求完成(成功或失败)时,减少计数器,并检查队列中是否还有待执行的请求,如有则继续执行。
  2. 请求重试机制
    • 在请求失败时,根据重试次数进行重试。
    • 每次重试间隔递增,可以使用指数退避算法,例如每次重试间隔是前一次的2倍。
  3. 全局请求和响应拦截器
    • 创建一个函数来注册全局的请求和响应拦截器。
    • 利用axiosinterceptors功能来实现。

核心代码示例

import axios from 'axios';
import { ref } from 'vue';

// 最大并发数
const maxConcurrent = 3;
// 存储请求队列
const requestQueue = [];
// 当前正在执行的请求数量
const activeRequests = ref(0);

// 注册全局请求拦截器
axios.interceptors.request.use(config => {
  // 在这里可以对请求进行统一处理,例如添加token等
  return config;
}, error => {
  return Promise.reject(error);
});

// 注册全局响应拦截器
axios.interceptors.response.use(response => {
  // 在这里可以对响应进行统一处理,例如检查登录状态等
  return response;
}, error => {
  return Promise.reject(error);
});

// 封装网络请求函数
const request = async (config, retries = 3, retryInterval = 1000) => {
  return new Promise((resolve, reject) => {
    const executeRequest = async () => {
      try {
        activeRequests.value++;
        const response = await axios(config);
        resolve(response);
      } catch (error) {
        if (retries > 0) {
          await new Promise(resolve => setTimeout(resolve, retryInterval));
          await executeRequest(config, retries - 1, retryInterval * 2);
        } else {
          reject(error);
        }
      } finally {
        activeRequests.value--;
        if (requestQueue.length > 0 && activeRequests.value < maxConcurrent) {
          requestQueue.shift()();
        }
      }
    };

    if (activeRequests.value >= maxConcurrent) {
      requestQueue.push(executeRequest);
    } else {
      executeRequest();
    }
  });
};

export default request;

在Vue组件中使用:

<template>
  <div>
    <button @click="fetchData">Fetch Data</button>
  </div>
</template>

<script setup>
import request from './request';

const fetchData = async () => {
  try {
    const response = await request({
      url: '/api/data',
      method: 'get'
    });
    console.log(response.data);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
};
</script>