如何解决页面请求接口大规模并发问题

在前端开发中,页面请求接口大规模并发可能会导致浏览器性能下降、服务器压力过大、接口响应超时等问题。以下是一些常见的解决方法:

1. 限制并发请求数量

通过自定义请求队列,控制同时发起的请求数量,避免过多请求同时发出。

示例代码

javascript 复制代码
class RequestQueue {
    constructor(maxConcurrency) {
        this.maxConcurrency = maxConcurrency;
        this.currentConcurrency = 0;
        this.queue = [];
    }

    addRequest(request) {
        return new Promise((resolve, reject) => {
            const task = () => {
                this.currentConcurrency++;
                request()
                   .then((result) => {
                        resolve(result);
                    })
                   .catch((error) => {
                        reject(error);
                    })
                   .finally(() => {
                        this.currentConcurrency--;
                        if (this.queue.length > 0) {
                            const nextTask = this.queue.shift();
                            nextTask();
                        }
                    });
            };

            if (this.currentConcurrency < this.maxConcurrency) {
                task();
            } else {
                this.queue.push(task);
            }
        });
    }
}

// 使用示例
const queue = new RequestQueue(3); // 最大并发数为 3

function fetchData(id) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`Fetched data for id ${id}`);
            resolve(id);
        }, 1000);
    });
}

const requests = Array.from({ length: 10 }, (_, i) => () => fetchData(i));

requests.forEach((request) => {
    queue.addRequest(request).then((result) => {
        console.log(`Result: ${result}`);
    });
});

2. 合并请求

将多个相关的请求合并为一个请求,减少请求次数。

示例场景

例如,在电商页面中,需要获取多个商品的信息,可以将这些商品的 ID 一次性传递给后端接口,后端返回这些商品的详细信息。

javascript 复制代码
// 假设我们有多个商品 ID
const productIds = [1, 2, 3, 4, 5];

// 合并请求
fetch(`/api/products?ids=${productIds.join(',')}`)
  .then((response) => response.json())
  .then((data) => {
        console.log(data);
    });

3. 节流与防抖

  • 节流(Throttle):在一定时间内,只执行一次请求。适用于需要频繁触发的请求,如滚动加载数据。
  • 防抖(Debounce):在一定时间内,只有最后一次触发的请求会被执行。适用于搜索框输入提示等场景。

节流示例代码

javascript 复制代码
function throttle(func, delay) {
    let timer = null;
    return function() {
        if (!timer) {
            func.apply(this, arguments);
            timer = setTimeout(() => {
                timer = null;
            }, delay);
        }
    };
}

// 使用示例
function fetchDataOnScroll() {
    console.log('Fetching data on scroll');
    // 发起请求
}

window.addEventListener('scroll', throttle(fetchDataOnScroll, 500));

防抖示例代码

javascript 复制代码
function debounce(func, delay) {
    let timer = null;
    return function() {
        clearTimeout(timer);
        timer = setTimeout(() => {
            func.apply(this, arguments);
        }, delay);
    };
}

// 使用示例
function searchData(query) {
    console.log(`Searching for ${query}`);
    // 发起搜索请求
}

const input = document.getElementById('search-input');
input.addEventListener('input', debounce((e) => {
    searchData(e.target.value);
}, 300));

4. 缓存机制

对于一些不经常变化的数据,可以使用缓存机制,避免重复请求。

示例代码

javascript 复制代码
const cache = {};

function fetchDataWithCache(url) {
    if (cache[url]) {
        return Promise.resolve(cache[url]);
    }

    return fetch(url)
      .then((response) => response.json())
      .then((data) => {
            cache[url] = data;
            return data;
        });
}

// 使用示例
fetchDataWithCache('/api/data')
  .then((data) => {
        console.log(data);
    });

5. 分批次请求

将大量请求分成多个批次,依次发送请求,避免一次性发送过多请求。

示例代码

javascript 复制代码
const requests = Array.from({ length: 20 }, (_, i) => () => fetch(`/api/data/${i}`));
const batchSize = 5;

function sendRequestsInBatches() {
    const batch = requests.splice(0, batchSize);
    if (batch.length === 0) {
        return Promise.resolve();
    }

    const promises = batch.map((request) => request());
    return Promise.all(promises).then(() => sendRequestsInBatches());
}

sendRequestsInBatches().then(() => {
    console.log('All requests completed');
});
相关推荐
oil欧哟1 分钟前
🥳 做了三个月的学习卡盒小程序,开源了!
前端·vue.js·微信小程序
奶球不是球5 分钟前
el-table(elementui)表格合计行使用以及滚动条默认样式修改
前端·vue.js·elementui
liuyang___7 分钟前
vue管理布局左侧菜单栏NavMenu
前端·javascript·vue.js
@业精于勤荒于嬉16 分钟前
将图片存储至阿里云 OSS
前端·阿里云·云计算·oss
打野赵怀真41 分钟前
render函数中return如果没有使用()会有什么问题?
前端·javascript
Riesenzahn43 分钟前
写一个左中右的满屏布局,左右固定220px,中间自适应并且要优先加载
前端·javascript
Riesenzahn44 分钟前
css在页面上画一个正方形,边长为页面宽度的一半
前端·javascript
tommyrunner1 小时前
Cursor rule文件测试 一秒了解AI行为规则文件
前端·cursor
北京_宏哥1 小时前
《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
java·前端·selenium