You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的短连接频率限制,提升连接失败概率。
修复方案

核心修改点:

  1. 给getCurrentPrice()调用加await,保证所有请求、写入逻辑跑完后函数再返回结果
  2. 删除冗余的agent: false配置,复用默认连接池
  3. 清理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:51:17