Skip to content
扫码开始移动端阅读

优化异步函数请求性能

1195
需要≈
5.975
分钟
基础知识
web

引言

在前端开发中,异步请求几乎无处不在,但我们经常会遇到这样的情况:为了获取数据,每次调用函数都会触发新的网络请求。这种方式虽然简单直接,却容易导致性能问题,特别是在高频调用或者网络资源有限的场景下。💡 如何用更优雅的方式优化异步请求,是提升代码质量的关键。本文将带你从最简单的优化方案出发,一步步深入探讨适合不同场景的解决方案。

场景还原

假设我们有如下代码:

javascript
const fetchData = async () => {
  const response = await fetch('/api/data.json');
  return response.json();
};

// 🔁 多次调用
fetchData();
fetchData();
fetchData();

每次调用 fetchData,都会发起一次新的 HTTP 请求,这在实际应用中可能造成资源浪费,尤其是接口数据在短时间内不会频繁更新时。如何解决这个问题?接下来我们将从最简单的实现开始,逐步优化。

优化方案逐步解析

1️⃣ 基础优化:简单缓存

为避免重复请求,可以使用一个变量缓存结果:

javascript
const fetchData = (() => {
  let cache = null;
  return async () => {
    if (!cache) {
      const response = await fetch('/api/data.json');
      cache = await response.json();
    }
    return cache;
  };
})();

// 🔄 多次调用
fetchData().then(console.log); // 第一次发送请求
fetchData().then(console.log); // 后续直接使用缓存

优点:实现简单,适合数据较为静态的场景。

缺点:一旦数据更新,缓存无法感知。这种方式更适用于只需加载一次的配置或静态数据。


2️⃣ 并发优化:Promise 共享

如果函数可能被多次并发调用,我们可以共享 Promise,确保多个调用共用同一个请求结果:

javascript
const fetchData = (() => {
  let promise = null;
  return async () => {
    if (!promise) {
      promise = fetch('/api/data.json').then(res => res.json());
    }
    return promise;
  };
})();

// 🤝 并发调用
Promise.all([fetchData(), fetchData(), fetchData()]).then(console.log);

优点:适合并发场景,所有调用共享相同的请求。

缺点:当请求失败时需要额外处理状态重置。


3️⃣ 动态优化:失效机制

如果数据需要定期更新,可以引入失效机制:

javascript
const fetchData = (() => {
  let cache = null;
  let timestamp = 0;
  const CACHE_DURATION = 60000; // ⏱️ 1分钟

  return async () => {
    const now = Date.now();
    if (!cache || now - timestamp > CACHE_DURATION) {
      const response = await fetch('/api/data.json');
      cache = await response.json();
      timestamp = now;
    }
    return cache;
  };
})();

// 📲 调用
fetchData().then(console.log);

优点:适合有时效性需求的数据,例如每隔一段时间刷新。

缺点:需要多写几行逻辑代码,但对性能影响显著。


4️⃣ 服务端优化:HTTP 缓存协作

通过利用 HTTP 的 ETagLast-Modified 头,确保只有数据更新时才重新请求:

javascript
const fetchData = (() => {
  let cache = null;
  let etag = '';

  return async () => {
    const response = await fetch('/api/data.json', {
      headers: { 'If-None-Match': etag },
    });

    if (response.status === 200) {
      etag = response.headers.get('ETag');
      cache = await response.json();
    }
    return cache;
  };
})();

fetchData().then(console.log);

优点:节省流量,数据更新透明化。

缺点:需要服务端支持。


5️⃣ 综合优化:集成多策略

在复杂场景下,可以结合多个策略实现灵活的优化方案:

javascript
const fetchData = (() => {
  let cache = null;
  let etag = '';
  let timestamp = 0;
  const CACHE_DURATION = 60000; // ⏱️ 1分钟

  return async () => {
    const now = Date.now();
    if (!cache || now - timestamp > CACHE_DURATION) {
      const response = await fetch('/api/data.json', {
        headers: { 'If-None-Match': etag },
      });

      if (response.status === 200) {
        etag = response.headers.get('ETag');
        cache = await response.json();
      }
      timestamp = now;
    }
    return cache;
  };
})();

fetchData().then(console.log);

这种方法结合了失效机制和服务端协作,可以满足更多复杂场景下的需求。


提示

在实际项目中,优雅地管理异步请求不仅能提升性能,还能让代码更易维护。

总结与对比

方法适用场景优点缺点
🧊 简单缓存静态数据实现简单,减少重复请求无法感知数据更新
🤝 Promise 共享并发调用共享请求结果,避免重复发送需额外处理状态异常
⏱️ 失效机制定期更新的数据数据更新及时,性能高效缓存逻辑稍显复杂
🔄 服务端协作动态更新数据减少流量消耗,透明化更新依赖服务端支持
🛠️ 综合优化复杂多变的场景灵活组合,应对复杂场景实现较复杂,开发成本增加

从简单缓存到综合优化,我们探索了多种提升异步函数性能的方式。根据你的实际需求,选择合适的方案,将极大提升用户体验与系统效率!🚀

上次更新: