JavaScript新手:高频调用REST API触发Socket错误的解决咨询
解决高频REST POST调用导致的Socket错误问题
嘿,这个坑我之前踩过!连续高频调用API的时候,不管是服务端的并发限制,还是客户端的Socket连接池被耗尽,都容易触发这类错误。针对你的700行CSV数据场景,给你几个实用的调整方案,按优先级和复杂度排序:
1. 优先尝试:批量上传数据(最优解)
如果你的REST服务支持接收批量数据,这绝对是最好的选择。把多行CSV数据打包成一个请求发送,直接把请求次数从700次降到十几到几十次,从根源上解决调用频繁的问题。
举个代码示例:
// 假设你已经把CSV解析成了数组dataArray const batchSize = 50; // 每50条数据发一次请求,可根据服务端承受能力调整 for (let i = 0; i < dataArray.length; i += batchSize) { const batchData = dataArray.slice(i, i + batchSize); try { await fetch('你的API地址', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(batchData) }); // 批次之间可以加个短延迟,进一步降低压力 await new Promise(resolve => setTimeout(resolve, 50)); } catch (err) { console.error(`上传批次 ${Math.floor(i/batchSize) + 1} 失败:`, err); // 这里可以加重试逻辑,后面会提到 } }
注意:如果服务端还不支持批量接口,最好和后端同学沟通一下,批量处理不管是前端还是后端效率都会高很多。
2. 并发控制(适合无法批量的场景)
如果必须逐行调用API,那就要控制同时发起的请求数量,避免一下子占满所有Socket连接。你可以用npm上的p-limit包来轻松实现,这是Node.js生态里处理并发限制的常用工具。
步骤如下:
首先安装依赖:
npm install p-limit
然后编写代码:
const pLimit = require('p-limit'); const limit = pLimit(5); // 限制同时最多5个请求并发 // 把每个上传任务包装成受限制的异步函数 const uploadTasks = dataArray.map(item => limit(async () => { try { await fetch('你的API地址', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(item) }); } catch (err) { console.error(`上传数据失败:`, err); } })); // 等待所有任务完成 await Promise.all(uploadTasks);
这个方法既不会像逐行同步调用那样慢,又不会因为并发太高触发错误,平衡了效率和稳定性。
3. 简单临时方案:添加固定延迟
如果上面两种方案暂时没法实现,最快速的临时解决方法就是在每次请求后加一个固定延迟,降低调用频率。
写个简单的sleep函数:
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 然后在每次上传后调用 for (const item of dataArray) { await fetch('你的API地址', { /* 请求配置 */ }); await sleep(100); // 等待100毫秒,可根据实际情况调整 }
这个方法虽然简单,但效率最低,700条数据要等一分多钟,适合临时救急。
4. 锦上添花:添加错误重试机制
不管用上面哪种方法,都建议加上重试逻辑——网络请求偶尔失败很正常,尤其是高频调用时。可以用指数退避的方式,失败后等待一段时间再重试,每次等待时间翻倍。
示例重试函数:
async function fetchWithRetry(url, options, retries = 3, delay = 1000) { try { const response = await fetch(url, options); if (!response.ok) { throw new Error(`HTTP错误: ${response.status}`); } return response; } catch (err) { if (retries > 0) { console.log(`请求失败,${delay}毫秒后重试,剩余重试次数:${retries}`); await new Promise(resolve => setTimeout(resolve, delay)); return fetchWithRetry(url, options, retries - 1, delay * 2); } throw err; // 重试耗尽后抛出错误,方便后续处理 } }
把之前的fetch替换成这个函数,遇到Socket错误或者HTTP错误时会自动重试,大大提高上传成功率。
内容的提问来源于stack exchange,提问作者burix




