Firebase Functions用node-fetch批量请求IEXCloud API二次调用报TLS断连
问题根因
两个直接触发错误的核心问题:
- 异步逻辑未等待执行完成:你在
onRun执行流里直接调用了异步函数getCurrentPrice(),但没有加await等待它执行完毕,就直接执行了return Promise.all(promises)。此时promises数组是空的,Cloud Functions收到resolve的返回值后,会立刻冻结当前实例的CPU、网络资源,准备回收实例。第一次请求刚好赶在资源冻结前完成了响应和写入,第二次请求发起时TLS握手还没走完,底层套接字已经被强制断开,就会抛出你看到的TLS连接建立前套接字断开的错误。 - fetch配置不合理:你给请求加了
agent: false配置,这个参数会禁用Node.js默认的HTTPS连接池复用机制,每次请求都要重新做TCP建连、TLS握手,既会拉长请求耗时,也容易触发IEX Cloud的短连接频率限制,提升连接失败概率。
修复方案
核心修改点:
- 给
getCurrentPrice()调用加await,保证所有请求、写入逻辑跑完后函数再返回结果 - 删除冗余的
agent: false配置,复用默认连接池 - 清理async/await混写的冗余逻辑,移除没用的空
promises数组
const functions = require("firebase-functions"); const fetch = require("node-fetch"); const admin = require("firebase-admin"); admin.initializeApp(); const db = admin.firestore(); exports.scheduledFunctionCrontab = functions.pubsub .schedule("0 09-17 * * 1-5") .timeZone("America/New_York") .onRun(async () => { // 读取所有持仓文档ID const positionsSnap = await db.collection("positions").get(); const tempDoc = positionsSnap.docs.map(doc => doc.id); // 按100个一组拆分股票代码 const perChunk = 100; const positionsObject = tempDoc.reduce((resultArray, item, index) => { const chunkIndex = Math.floor(index / perChunk); if (!resultArray[chunkIndex]) { resultArray[chunkIndex] = []; } resultArray[chunkIndex].push(item); return resultArray; }, []); async function databaseWrite(json) { // 原有数据库写入逻辑保持不变即可 } async function getCurrentPrice() { for (const symbols of positionsObject) { const ourPositionsString = symbols.toString(); const API_Call = `https://sandbox.iexapis.com/stable/stock/market/batch?symbols=${ourPositionsString}&types=quote&token=TOKEN`; const fetchResponse = await fetch(API_Call, { method: "GET" }); const json = await fetchResponse.json(); await databaseWrite(json); } } // 等待所有拉取、写入逻辑执行完成再返回 await getCurrentPrice(); return null; });
额外优化建议
如果后续拆分的分组更多,连续请求还是偶尔出现连接错误,可以在两次请求之间加200ms左右的短延迟,比如await new Promise(resolve => setTimeout(resolve, 200)),避免短时间请求频率过高被IEX Cloud限流。
内容的提问来源于stack exchange,提问作者MrVerticalStack
相关产品推荐
相关产品推荐

