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

部署Firebase定时股票数据云函数报Maximum call stack size exceeded错误

报错根因

部署时栈溢出的直接原因是在Cloud Functions服务端环境错误引入了Firebase客户端Web SDK:你代码里用的firebase/app、firebase/firestore是面向浏览器、移动端客户端设计的SDK,在Node.js服务端环境加载解析时会触发递归调用逻辑,直接导致函数部署阶段生成manifest时抛出Maximum call stack size exceeded错误。

除此之外你的代码还有几个会导致运行异常的问题:

  • 日期计算逻辑写在函数全局作用域,只会在函数冷启动时执行一次,后续热启动的实例会一直复用第一次计算的日期,拉取到的永远是冷启动当天前一天的数据,不会每日更新
  • 循环调用setDoc时没有等待写入Promise完成,函数可能在数据写入Firestore之前就终止运行,导致数据丢失
  • 3000条文档并发单条写入很容易触发Firestore写入限流,拉高运行报错概率
  • 原cron表达式12 00 * * *实际是每日0点12分触发,和你要的12点触发需求不符
修复方案
  1. 先卸载错误的客户端SDK,安装服务端专用的Firebase Admin SDK,在functions目录下执行命令:
npm uninstall firebase
npm install firebase-admin
  1. 替换原有index.ts的代码,修正初始化逻辑、日期计算位置、写入逻辑,修复后完整代码如下:
import * as functions from "firebase-functions";
import axios from "axios";
import { getFirestore, Timestamp } from "firebase-admin/firestore";
import { format } from "date-fns";
import { initializeApp, getApps } from "firebase-admin/app";

// 初始化Admin SDK,加判断避免冷启动重复初始化报错
if (!getApps().length) {
  initializeApp();
}
const db = getFirestore();

const API_KEY = "****************";

interface StockItem {
  clpr: string;
  srtnCd: string;
}

export const getStocks = functions
  .region("asia-northeast3")
  .pubsub.schedule("0 12 * * *") // 修正为每日首尔时间12点整触发
  .timeZone("Asia/Seoul")
  .onRun(async (context) => {
    // 日期计算移到函数内部,每次触发重新计算最新日期
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    const basDt = format(yesterday, "yyyyMMdd");

    // 拉取股票数据
    const { data } = await axios.get(
      `https://api.odcloud.kr/api/GetStockSecuritiesInfoService/v1/getStockPriceInfo?numOfRows=3000&resultType=json&basDt=${basDt}&serviceKey=${API_KEY}`
    );
    const stockList: StockItem[] = data.response.body.items.item;

    // 分批次写入,Firestore单批次写入上限为500条,这里取400留冗余
    const BATCH_SIZE = 400;
    for (let i = 0; i < stockList.length; i += BATCH_SIZE) {
      const batch = db.batch();
      const chunk = stockList.slice(i, i + BATCH_SIZE);
      chunk.forEach((item) => {
        const docRef = db.doc(`KRX/${item.srtnCd}`);
        batch.set(docRef, {
          day: Timestamp.fromDate(today),
          price: item.clpr
        });
      });
      await batch.commit();
    }

    return null;
  });
补充说明
  • Admin SDK在Cloud Functions环境中会自动读取运行时绑定的服务账号权限,不需要手动填写客户端那套firebaseConfig参数,初始化更简单,权限也更高
  • 用批量写入(Batch Write)替代循环单条setDoc,既减少网络请求开销,也能避免并发写入触发限流
  • 所有异步操作都加了await,保证所有数据写入完成后函数才会退出,不会丢数据
  • 如果你确实需要每日0点12分触发,把schedule里的cron表达式改回12 00 * * *即可

内容的提问来源于stack exchange,提问作者신범기

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:01:06