一、为什么要优化网络请求?

现代Web应用中,网络请求的稳定性直接影响用户体验。尤其是在弱网环境下,请求失败率会显著上升。想象这样一个场景:用户在地铁上刷你的电商网站,商品列表接口时通时断,这时候若能自动重试失败请求并展示缓存数据,就能明显提升用户的浏览体验。

二、技术栈选择与基础搭建

(技术栈:Vue3 + Vite + VueUse)

// 项目初始化命令(确保Node.js >=14.18)
npm create vite@latest vueuse-demo --template vue-ts

// 安装依赖
npm install @vueuse/core axios

三、基础请求场景实现

// src/components/ArticleList.vue
<script setup lang="ts">
import { useFetch } from '@vueuse/core'

const { data, error } = useFetch('https://api.example.com/articles')
</script>

<template>
  <div v-if="error">哎呀,加载失败啦!</div>
  <ul v-else-if="data">
    <li v-for="article in JSON.parse(data)" :key="article.id">
      {{ article.title }}
    </li>
  </ul>
</template>

这时候我们获得了一个最基础的网络请求实现,但缺乏容错机制和性能优化。

四、智能重试机制实战

// 增强版请求配置
const { data, retry } = useFetch('https://api.example.com/articles', {
  // 失败时自动重试
  retry: 3, // 最大重试次数
  retryDelay: 1000, // 重试间隔(毫秒)
  timeout: 5000, // 单次请求超时时间
}, {
  // 响应拦截器
  afterFetch(ctx) {
    if (ctx.statusCode !== 200) {
      ctx.error = new Error('服务端异常')
    }
    return ctx
  }
}).json() // 自动解析JSON

// 手动重试按钮
<button @click="retry()" v-if="error">点击重试</button>

此时我们的请求具备自动容错能力,但频繁请求仍会造成服务器压力。

五、缓存策略深度应用

// 创建缓存管理器
const cacheManager = new Map<string, {
  timestamp: number
  data: any
}>()

const { data } = useFetch('https://api.example.com/articles', {
  // 开启缓存
  cache: 'force-cache',
  // 自定义缓存键
  cacheKey: 'article_list',
  // 自定义缓存处理
  cacheManager: {
    get: key => cacheManager.get(key),
    set: (key, value) => cacheManager.set(key, {
      timestamp: Date.now(),
      data: value
    }),
    has: key => cacheManager.has(key)
  },
  // 缓存有效期(10分钟)
  cacheMaxAge: 600_000
}).json()

现在我们的应用已具备本地内存缓存能力,但还需要处理缓存更新策略。

六、全功能集成示例

// 完整请求配置示例
const { data, error, retry, isFetching } = useFetch('https://api.example.com/articles', {
  // 缓存配置
  cache: 'force-cache',
  cacheKey: 'articles_v2',
  cacheMaxAge: 300_000,

  // 重试配置
  retry: 2,
  retryDelay: 2000,

  // 性能优化
  refetch: true, // 窗口重新聚焦时刷新
  timeout: 8000,

  // 请求头
  headers: {
    'Cache-Control': 'max-age=300'
  }
}, {
  // 请求拦截器
  beforeFetch({ options }) {
    options.headers.Authorization = `Bearer ${token.value}`
    return { options }
  },

  // 响应拦截器
  afterFetch(ctx) {
    if (ctx.data.code !== 0) {
      ctx.error = new Error(ctx.data.message)
    }
    return ctx
  }
}).json()

七、技术实现注意事项

  1. 缓存键设计:推荐使用接口路径+参数哈希的方式生成唯一标识
  2. 内存管理:对于大容量数据建议实现LRU缓存淘汰策略
  3. 错误边界:需要区分网络错误、超时错误和业务逻辑错误
  4. TypeScript支持
interface Article {
  id: number
  title: string
  content: string
}

// 声明响应类型
const { data } = useFetch<Article[]>('...').json()

八、方案优劣势分析

优点:

  • 开发效率提升:开箱即用的重试/缓存机制
  • 代码可维护性:集中化的请求配置管理
  • 用户体验优化:无缝衔接的失败恢复机制

缺点:

  • 内存缓存不适合大规模数据
  • 嵌套请求处理能力有限
  • 文件上传等特殊场景需要特殊处理

九、最佳实践建议

  1. 结合IndexedDB实现持久化缓存
  2. 为重要请求配置更高优先级
  3. 实现可视化的请求瀑布流监控
  4. 在导航离开时自动取消非必要请求

十、应用场景展望

此方案特别适合以下场景:

  • 实时性要求不高的资讯类应用
  • 电商平台的商品详情页面
  • 移动端弱网环境下的列表展示
  • 需要降低服务器压力的公共接口