Node发起HTTP请求时内存充足却触发ENOMEM错误(macOS环境)
问题分析与解决方案
错误根源:并发连接耗尽系统套接字资源
你遇到的ENOMEM错误不是V8堆内存不足,而是系统层面的套接字(socket)资源耗尽。问题出在递归调用的逻辑上:
原代码里递归调用search(count + LENGTH)时没加await,这会导致当前请求还没完成,就立刻发起下一个请求。短时间内会产生大量并发HTTP连接,每个连接都会占用一个操作系统的文件描述符(套接字属于文件描述符的一种)。macOS对单进程可打开的文件描述符数量有默认限制,一旦突破上限,系统就会返回ENOMEM错误——内核无法为新的套接字分配资源。
你观察到堆内存未超150MB是正常的:--max-old-space-size只控制V8引擎的JavaScript堆内存,和系统内核管理的套接字资源是完全独立的两个内存区域。
脚本问题修正
1. 修复递归调用,改为串行请求
给递归调用加上await,确保上一个请求完成后再发起下一个,避免并发连接爆炸:
let all_items = [] async function search(start = 0) { params.set('start', start) const r = await fetch(`${options.url}/api/search/?${params.toString()}`, { headers: headers }) if (!r.ok) console.error(`HTTP error: ${r.status} ${r.statusText}`) const d = await r.json() // API error messages if (d.error) throw new Error(`${d.code} ${d.error}: ${d.error_description}`) // 修正笔误:data.results -> d.results all_items.push(...d.results) const count = all_items.length if (count < d.available) { console.log(`Getting items ${count + 1} through ${count + LENGTH}...`) // 添加await,串行执行下一次请求 await search(count + LENGTH) } }
2. 修正变量笔误
原代码中data.results和data.available应该是d.results和d.available——你把接口返回的JSON数据存在了变量d中。
补充说明
如果想提升效率,也可以控制并发请求数量(比如同时发起3-5个请求),但对于3万条数据来说,串行请求已经足够稳定,且不会触发系统资源限制。
内容的提问来源于stack exchange,提问作者phette23
相关产品推荐
相关产品推荐

