网络请求技能进阶指南:从基础封装到高并发优化

4次阅读
没有评论

共计 1488 个字符,预计需要花费 4 分钟才能阅读完成。

image.webp

糟糕的网络请求实现会带来什么问题

想象一下电商秒杀场景:当某个热门商品开售时,由于前端没有做好请求队列管理,瞬间爆发的上万次请求直接击垮服务器。又或者在一个实时聊天应用中,因为缺乏重试机制和错误处理,网络波动导致消息频繁发送失败。这些都是网络请求层设计不当引发的典型问题。

网络请求技能进阶指南:从基础封装到高并发优化

技术选型:Axios vs Fetch

拦截器机制差异

  • Axios:提供了完善的请求和响应拦截器,可以在请求发出前和响应返回后统一处理数据
  • Fetch:原生不支持拦截器,需要自行封装或使用第三方库实现类似功能

取消请求实现方式

  • Axios:内置 CancelToken API(新版本也支持 AbortController)
  • Fetch:必须配合 AbortController 使用

TypeScript 支持度

  • Axios:有完整类型定义,开箱即用
  • Fetch:需要额外定义响应类型,接口灵活性更高但开发成本稍大

核心实现

请求封装类 (TypeScript)

/**
 * 网络请求封装类
 * @param baseURL 基础 API 地址
 * @param timeout 超时时间 (ms)
 */
class HttpRequest {constructor(private baseURL: string, private timeout = 5000) {}

  // 统一请求方法
  async request<T>(config: RequestConfig): Promise<T> {// 实现细节...}
}

错误重试策略(指数退避)

async function requestWithRetry(requestFn: () => Promise<any>,
  maxRetries = 3,
  baseDelay = 1000
) {
  let attempt = 0
  while (attempt < maxRetries) {
    try {return await requestFn()
    } catch (error) {
      attempt++
      if (attempt >= maxRetries) throw error

      // 指数退避延迟
      const delay = baseDelay * Math.pow(2, attempt)
      await new Promise(resolve => setTimeout(resolve, delay))
    }
  }
}

请求缓存实现

const cache = new Map<string, {data: any; expire: number}>()

function getCache(key: string) {const item = cache.get(key)
  if (!item || Date.now() > item.expire) {cache.delete(key)
    return null
  }
  return item.data
}

性能优化

连接池配置

  • HTTP/1.1 下浏览器对同一域名有 6 - 8 个连接限制
  • 合理设置 keep-alive 可以复用 TCP 连接

压缩策略

  • 服务端开启 gzip/brotli 压缩
  • 请求头设置 Accept-Encoding

并发控制(令牌桶算法)

class RateLimiter {constructor(private maxTokens, private refillRate) {// 初始化...}

  async acquire() {// 获取令牌逻辑}
}

生产环境避坑指南

Cookie 安全设置

  • 关键 Cookie 设置 HttpOnly 和 Secure
  • 合理设置 SameSite 属性

CSRF 防护实践

  • 使用 CSRF Token
  • 验证 Referer 头

内存泄漏排查

  • 检查未取消的请求
  • 监控 EventListener 数量

思考题

  1. 如何设计离线优先的请求队列?
  2. 在微服务架构下如何统一请求监控?
  3. 针对 API 频繁变更的场景,如何设计更灵活的请求层?
正文完
 0
评论(没有评论)