如何在Firebase云函数中部署setInterval循环使其持续运行?
问题根本原因
你使用的Firebase Cloud Functions是无服务事件驱动架构,函数实例只会在收到触发请求时启动,请求处理完成后最多存活数分钟就会被系统回收,你写在函数里的setInterval根本不可能长期持续运行,这就是为什么跑10次左右就停止,必须重新输入消息触发函数重启才能继续。
现有代码的其他隐性问题
- 异步逻辑顺序错误:
axios.get是异步请求,你没有等待请求返回就直接调用quickstartAddData写数据库,存入的status大概率是上一次的旧值甚至是未赋值的初始状态 - 数据写入逻辑错误:你用
set方法写入固定id为mmAnPhu的文档,每次执行都是覆盖同一条记录,并不会新增聊天消息,正常应该调用add方法生成新文档,才能在聊天窗口里看到逐条新增的历史事件 - 时区处理不规范:直接给小时加7的写法容易出现边界错误,建议直接用指定时区的时间格式化方法生成时间字符串
正确实现方案
用Firebase官方提供的计划云函数替代setInterval,这是专门用于定时执行任务的原生能力,完全适配你的需求。
修改后的代码示例(替换你原有index.js里的相关代码)
const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); const db = admin.firestore(); const axios = require('axios'); const cheerio = require('cheerio'); const https = require('https'); const url = 'https://online.mmvietnam.com/trung-tam/mm-an-phu/'; // 定义每分钟执行一次的计划函数 exports.syncMegaMarketStatus = functions.pubsub.schedule('every 1 minutes').onRun(async (context) => { // 处理时间,指定UTC+7时区,避免手动计算小时的边界错误 const datetime = new Intl.DateTimeFormat('vi-VN', { timeZone: 'Asia/Ho_Chi_Minh', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).format(new Date()); let status = 'CLOSED'; const agent = new https.Agent({ rejectUnauthorized: false }); try { const response = await axios.get(url, { httpsAgent: agent }); const $ = cheerio.load(response.data); const text = $('.vertical-wrapper .text-title').html(); if (text !== null) { status = 'OPEN'; } } catch (err) { console.error('请求页面失败:', err); } // 新增消息文档,而非覆盖旧文档 await db.collection('messages').add({ name: 'Thu', text: `${datetime} Mega market An Phu ${status}`, profilePicUrl: 'CamThu', timestamp: admin.firestore.FieldValue.serverTimestamp() // 用服务端时间戳更准确 }); return null; });
部署注意事项
- 需要在Google Cloud控制台开启Cloud Scheduler API
- 计划云函数需要使用Firebase Blaze付费计划,按量计费的免费额度完全覆盖这种低频定时任务的消耗
- 部署后函数会自动每分钟执行一次,不需要任何前端触发,前端只要保持监听
messages集合的更新,就会自动收到新的事件消息
内容的提问来源于stack exchange,提问作者Thu Nguyen
相关产品推荐
相关产品推荐

