使用Firebase Emulators PubSub测试定时函数出现重复调用如何解决
问题根因
重复触发的问题确实是setInterval被多次注册导致的:Firebase Functions模拟器默认开启热重载,每次代码变更、模拟器重新加载index.js文件时,之前注册的定时器不会被自动销毁,每加载一次就会新增一个定时器,最终出现每分钟触发次数随加载次数递增的情况。
另外你提供的代码存在语法问题:setInterval的回调函数中使用了await,但没有声明async,实际运行会直接报错。
解决方案
下面是两种常用的修复方案:
方案1:注册定时器前清理已有实例(适合将触发逻辑和函数代码放在一起的场景)
通过全局变量存储定时器ID,每次注册新定时器前先销毁旧实例,避免重复创建,修改后的代码如下:const { PubSub } = require('@google-cloud/pubsub'); const pubsub = new PubSub({ apiEndpoint: 'localhost:8085' }); // 清理前一次热重载遗留的定时器 if (global._localPubsubScheduleTimer) { clearInterval(global._localPubsubScheduleTimer); } // 回调必须加async修饰,否则await语法不生效 global._localPubsubScheduleTimer = setInterval(async () => { const SCHEDULED_FUNCTION_TOPIC = 'firebase-schedule-yourFunctionName'; console.log(`Trigger scheduled function via PubSub topic: ${SCHEDULED_FUNCTION_TOPIC}`); const msg = await pubsub.topic(SCHEDULED_FUNCTION_TOPIC).publishJSON({ foo: 'bar', }, { attr1: 'value1' }); }, 1 * 60 * 1000); // 每1分钟触发一次方案2:使用独立触发脚本(更推荐,不受热重载影响)
不要将setInterval逻辑写在Cloud Functions的index.js文件中,单独新建一个local-schedule-trigger.js文件,只保留定时器和PubSub发布逻辑,单独用node local-schedule-trigger.js命令运行该脚本,和Firebase模拟器进程完全隔离,从根源上避免定时器重复注册的问题。
如果是临时测试不想修改代码,每次修改函数代码后手动重启Firebase模拟器,也可以临时解决重复触发问题,不过长期调试更推荐上面两种方案。
内容的提问来源于stack exchange,提问作者Redneys
相关产品推荐
相关产品推荐

