前端假如有几十个请求,如何去控制并发

B站影视 2025-01-08 20:51 2

摘要:async function fetchWithConcurrency(urls, maxConcurrency) {const results = ;while (urls.length > 0) {// 取出一批URLconst batch = urls.

在处理大量并发请求时,为了避免服务器过载或客户端性能下降,可以使用并发控制技术。以下是几种常见的方式:

将请求分成小批次,并逐批执行,每一批的大小由并发限制决定:

async function fetchWithConcurrency(urls, maxConcurrency) {const results = ;while (urls.length > 0) {// 取出一批URLconst batch = urls.splice(0, maxConcurrency);// 使用 Promise.allSettled 执行一批请求const batchResults = await Promise.allSettled(batch.map(url => fetch(url)));results.push(...batchResults);}return results;}const urls = Array(100).fill('https://example.com/api');fetchWithConcurrency(urls, 5).then(results => {console.log(results); // 输出每个请求的状态与结果});

创建一个队列控制器,通过限制同时运行的 Promise 数量来管理并发:

class PromiseQueue {constructor(maxConcurrency) {this.maxConcurrency = maxConcurrency;this.running = 0;this.queue = ;}enqueue(task) {return new Promise((resolve, reject) => {this.queue.push( => task.then(resolve, reject));this.runNext;});}runNext {if (this.running >= this.maxConcurrency || this.queue.length === 0) {return;}const task = this.queue.shift;this.running++;task.finally( => {this.running--;this.runNext;});}}// 使用队列const queue = new PromiseQueue(5); // 并发数为 5const urls = Array(100).fill('https://example.com/api');Promise.all(urls.map(url => queue.enqueue( => fetch(url)))).then(results => {console.log(results);});

可以使用现成的库如 p-limit 或 promise-pool 来管理并发。

const pLimit = require('p-limit');const limit = pLimit(5); // 最大并发数 5const urls = Array(100).fill('https://example.com/api');const tasks = urls.map(url => limit( => fetch(url)));Promise.all(tasks).then(results => {console.log(results);});const { promisePool } = require('promise-pool');const urls = Array(100).fill('https://example.com/api');async function fetchUrl(url) {const response = await fetch(url);return response.json;}promisePool({ items: urls, concurrency: 5, task: fetchUrl }).then(results => {console.log(results);});

结合超时机制,使用 AbortController 提前中止请求,防止某些请求过长拖慢整个流程:

async function fetchWithTimeout(url, timeout = 5000) {const controller = new AbortController;const signal = controller.signal;const timeoutId = setTimeout( => controller.abort, timeout);try {const response = await fetch(url, { signal });return await response.json;} catch (err) {return { error: 'Timeout or network error' };} finally {clearTimeout(timeoutId);}}// 并发控制逻辑同上

来源:科技黑讲堂

相关推荐