js中如何多次取分页数据

在JavaScript中,当需要通过fetch接口分页获取大量数据(如每次获取100条,共需几十次请求)时,频繁的同步请求会导致性能瓶颈(如网络延迟累积、主线程阻塞等)。以下是优化方案及实现思路:

一、并发请求优化

  1. 使用Promise.all并行请求
    通过将多个分页请求封装为Promise,并利用Promise.all同时发起多个请求,减少总耗时。例如,每次同时请求3页数据,分19组完成57次请求:
    const fetchDataInBatches = async (startPage, endPage, perPage = 100) => {
      const promises = [];
      for (let page = startPage; page <= endPage; page++) {
        const url = `/api/data?page=${page}&size=${一页大小}`;
        promises.push(fetch(url).then(response => response.json()));
      }
      return Promise.all(promises);
    };
    // 分19组,每组3页
    const allData = [];
    for (let i = 0; i < 19; i++) {
      const batchData = await fetchDataInBatches(i * 3 + 1, (i + 1) * 3);
      allData.push(...batchData扁平化处理);
    }
    
    注意:需确保服务器支持并发请求,避免触发限流策略。
  2. 动态调整并发数
    根据网络状况动态控制并发请求数量,例如使用队列机制逐步释放请求:
    const MAX_CONCURRENT = 5; // 最大并发请求数
    const queue = dataPages; // 所有分页数据列表
    const results = [];
    const processNext = async () => {
      if (queue.length === 0) return;
      const page = queue.shift();
      const result = await fetch(page.url).then(response => response.json());
      results.push(result);
      processNext(); // 递归处理下一个请求
    };
    // 同时启动MAX_CONCURRENT个请求
    for (let i = 0; i < MAX_CONCURRENT; i++) {
      processNext();
    }
    
    此方法避免一次性占用过多资源,提升稳定性。

二、后端协作优化

  1. 增大单页数据量
    与后端协商,将每页数据量从100条提升至更高值(如200条),直接减少请求次数。例如:
    // 调整分页参数
    const fetchData = async (page, size = 200) => {
      const url = `/api/data?page=${page}&size=${size}`;
      return await fetch(url).then(response => response.json());
    };
    
    优势:显著降低请求次数,减少网络开销。
  2. 流式传输或分块响应
    若后端支持流式传输(如Transfer-Encoding: chunked),可逐步接收数据并处理,避免等待所有数据返回:
    const streamData = async () => {
      const response = await fetch('/api/data/stream');
      const reader = response.body.getReader();
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        const chunk = new TextDecoder().decode(value);
        processChunk(chunk); // 逐块处理数据
      }
    };
    
    此方法适用于实时处理场景。

三、前端性能增强

  1. 使用Web Workers处理耗时任务
    将数据解析或处理逻辑移至后台线程,避免阻塞主线程:
    // 主线程
    const worker = new Worker('data-processor.js');
    worker.postMessage({ pages: dataPages });
    worker.onmessage = (event) => handleResult(event.data);
    // data-processor.js(Worker线程)
    onmessage = (event) => {
      const processedData = event.data pages.map(page => process(page));
      postMessage(processedData);
    };
    
    适用场景:数据量极大或需复杂计算时。
  2. 缓存与增量加载
    结合Cache APIService Worker缓存已请求数据,减少重复请求:
    // 使用Cache API
    const cacheKey = `/api/data?page=${page}`;
    const cache = await caches.open('data-cache');
    const response = await cache.match(cacheKey);
    if (!response) {
      const fetchResponse = await fetch(cacheKey);
      cache.put(cacheKey, fetchResponse.clone());
      response = fetchResponse;
    }
    return await response.json();
    
    注意:需权衡缓存有效期与数据实时性。

四、错误处理与重试机制

  1. 自动重试失败请求
    为每个请求添加重试逻辑,避免因网络波动导致数据丢失:
    const retryFetch = async (url, retries = 3) => {
      try {
        const response = await fetch(url);
        if (!response.ok) throw new Error(`Request failed: ${response.status}`);
        return response.json();
      } catch (error) {
        if (retries > 0) return retryFetch(url, retries - 1);
        throw error;
      }
    };
    
    建议:结合指数退避策略(如1s, 2s, 4s延迟重试)。

五、总结与建议

  1. 优先与后端协作:增大单页数据量或支持流式传输是最直接的优化方式。
  2. 并发请求与动态队列:平衡并发数与稳定性,避免资源耗尽。
  3. 异步与多线程:使用Web Workers处理耗时任务,提升用户体验。
  4. 缓存与重试:增强容错性并减少冗余请求。
    通过上述方法,可显著减少多次请求的总耗时,同时保持代码的可维护性和鲁棒性。
posted @ 2025-03-22 20:46  卓能文  阅读(103)  评论(0)    收藏  举报