php前端接口请求过多、重复

一、成因分析

  1. 页面/组件初始化时并发发起大量接口请求
  2. 多个组件/页面重复请求同一数据
  3. 滚动、输入等高频事件触发频繁请求
  4. 用户操作过快导致重复提交
  5. 缓存未利用,数据每次都重新拉取
  6. 前端路由切换未做请求管理

二、优化方案与代码示例

1. 接口合并(API聚合)

  • 后端提供聚合接口,一次请求返回多个数据,减少请求次数

后端PHP示例:

// /api/homepage
return [
    'banners' => getBanners(),
    'hot_articles' => getHotArticles(),
    'user_info' => getUserInfo($userId),
];

前端调用:

fetch('/api/homepage').then(res => res.json()).then(data => {
    // 一次性渲染多个模块
});

2. 前端请求去重/防抖/节流

请求去重(防止同一接口并发多次)

JS示例(简单版):

const pendingRequests = new Set();

function fetchOnce(url) {
    if (pendingRequests.has(url)) return;
    pendingRequests.add(url);
    fetch(url)
        .then(res => res.json())
        .finally(() => pendingRequests.delete(url));
}

防抖(debounce)/节流(throttle)高频事件

防抖:

function debounce(fn, delay) {
    let timer = null;
    return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), delay);
    }
}
// 用于搜索输入框
input.addEventListener('input', debounce(function(e) {
    fetch('/api/search?q=' + e.target.value);
}, 300));

节流:

function throttle(fn, delay) {
    let last = 0;
    return function(...args) {
        const now = Date.now();
        if (now - last > delay) {
            last = now;
            fn.apply(this, args);
        }
    }
}
// 用于滚动加载
window.addEventListener('scroll', throttle(loadMore, 200));

3. 前端数据缓存(本地/内存/全局状态)

  • 全局状态管理:如Vuex、Redux、Pinia等,页面/组件间共享数据,避免重复请求
  • 本地缓存:localStorage/sessionStorage/IndexedDB
  • 内存缓存:请求结果存变量,下次直接用

示例:

let userInfoCache = null;
function getUserInfo() {
    if (userInfoCache) return Promise.resolve(userInfoCache);
    return fetch('/api/user').then(res => res.json()).then(data => {
        userInfoCache = data;
        return data;
    });
}

4. 服务端缓存/接口合并

  • 后端缓存热点数据,如Redis、APCu,减少数据库压力
  • GraphQL:天然支持聚合查询

5. 请求合并(Batching)

  • 多个请求合并为一个(如GraphQL、RESTful批量接口)

RESTful批量接口示例:

// /api/batch?urls=/api/user,/api/notice
$urls = explode(',', $_GET['urls']);
$result = [];
foreach ($urls as $url) {
    $result[$url] = file_get_contents($url);
}
return $result;

6. 防止重复提交

  • 按钮禁用请求中标记唯一请求ID

示例:

let submitting = false;
function submitForm() {
    if (submitting) return;
    submitting = true;
    fetch('/api/submit', {method: 'POST', body: ...})
        .finally(() => submitting = false);
}

7. 路由切换时取消未完成请求

  • 用AbortController(Fetch)、axios的cancelToken等

Fetch示例:

let controller = new AbortController();
fetch('/api/data', { signal: controller.signal });
// 路由切换时
controller.abort();

三、监控与排查

  • Chrome DevTools Network:查看请求数量、重复请求
  • APM/埋点:统计接口QPS、重复率
  • 后端日志:分析高频/重复接口

四、实际优化流程举例

  1. 后端聚合接口,减少前端请求数
  2. 前端全局状态管理/本地缓存,避免重复拉取
  3. 高频事件用防抖/节流
  4. 请求去重、合并、批量处理
  5. 按钮禁用/唯一ID防止重复提交
  6. 监控和持续优化

五、总结

  • 接口请求过多、重复,核心是聚合、缓存、去重、合并、限流
  • 前后端协作,持续优化,监控不可少。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贵哥的编程之路(热爱分享 为后来者)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值