MST

星途 面试题库

面试题:Vue实现请求合并的具体方法及注意事项

请详细阐述在Vue项目里,怎样通过代码实现网络请求合并,比如合并多个相同接口但参数不同的请求。同时说明在实现过程中会遇到哪些问题,应该如何解决这些问题。
12.1万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

1. 实现网络请求合并的方法

在Vue项目中,可以借助Promise和一个请求队列来实现网络请求合并。以下是具体实现步骤:

  1. 创建请求队列: 使用一个对象来存储相同接口但不同参数的请求,对象的键可以是接口地址,值是一个数组,数组中存放每个请求的参数和对应的Promise
const requestQueue = {};
  1. 封装请求函数
import axios from 'axios';

function mergedRequest(url, params) {
  if (!requestQueue[url]) {
    requestQueue[url] = [];
  }
  return new Promise((resolve, reject) => {
    // 检查队列中是否已有相同参数的请求
    const existingRequest = requestQueue[url].find(req => req.params === params);
    if (existingRequest) {
      existingRequest.promise.then(resolve).catch(reject);
    } else {
      // 没有则添加到队列
      const newRequest = { params, promise: null };
      requestQueue[url].push(newRequest);
      if (requestQueue[url].length === 1) {
        // 只有一个请求时,发起实际请求
        axios.get(url, { params })
         .then(response => {
            requestQueue[url].forEach(req => req.promise.resolve(response));
            requestQueue[url] = [];
          })
         .catch(error => {
            requestQueue[url].forEach(req => req.promise.reject(error));
            requestQueue[url] = [];
          });
      }
      newRequest.promise = new Promise((innerResolve, innerReject) => {
        resolve = innerResolve;
        reject = innerReject;
      });
    }
  });
}
  1. 在Vue组件中使用
<template>
  <div>
    <button @click="fetchData">Fetch Data</button>
  </div>
</template>

<script>
export default {
  methods: {
    async fetchData() {
      const result1 = await mergedRequest('/api/data', { param1: 'value1' });
      const result2 = await mergedRequest('/api/data', { param1: 'value2' });
      console.log(result1, result2);
    }
  }
};
</script>

2. 实现过程中遇到的问题及解决方法

  • 问题1:请求队列清理不及时
    • 原因:如果请求队列没有及时清理,会导致内存占用过高,特别是在频繁发起请求的场景下。
    • 解决方法:在请求成功或失败后,及时清空请求队列。如上述代码中,在axios请求的thencatch回调中,都将requestQueue[url]置为空数组。
  • 问题2:参数处理复杂
    • 原因:当请求参数是复杂对象时,比较参数是否相同会变得复杂,简单的===比较无法满足需求。
    • 解决方法:可以使用JSON.stringify将参数对象转换为字符串进行比较,但要注意对象属性顺序可能影响结果。也可以使用更复杂的深度比较算法,如lodashisEqual方法。
  • 问题3:请求并发控制
    • 原因:如果同一时间有大量相同接口不同参数的请求进入队列,一次性发起可能会对服务器造成压力。
    • 解决方法:可以设置一个并发数限制,比如同一时间只允许发起一定数量的相同接口请求。可以使用Promise.allSettled结合队列分批处理请求。例如,将请求队列按并发数分组,依次处理每组请求。
function batchRequest(url, requests, concurrency) {
  const batches = [];
  for (let i = 0; i < requests.length; i += concurrency) {
    batches.push(requests.slice(i, i + concurrency));
  }
  return Promise.all(batches.map(batch => {
    const batchPromises = batch.map(req => axios.get(url, { params: req.params }));
    return Promise.allSettled(batchPromises);
  }));
}

在上述mergedRequest函数中,当需要发起实际请求时,调用batchRequest函数来控制并发。