定时触发器必须配置在云函数 package.json 中,而非代码内;云函数无状态、短生命周期,setInterval 等无效;仅通过 uniCloud 控制台或 package.json 的 trigger 字段声明才生效。

定时触发器必须配在云函数 package.json 里,不是写在代码里
很多人以为在 index.js 里写个 setInterval 或调用 setTimeout 就能实现定时,这是错的——云函数是无状态、短生命周期的,一旦执行完就销毁,setInterval 根本不会持续运行。真正生效的定时逻辑,只来自 uniCloud 控制台或 package.json 中声明的触发器配置。
正确做法是在云函数根目录(如 cloudfunctions/scheduledTask)下的 package.json 中添加 trigger 字段:
{
"name": "scheduledTask",
"main": "index.js",
"version": "1.0.0",
"trigger": {
"type": "timer",
"name": "dailyCleanup",
"config": "0 0 2 * * *"
}
}注意三点:
-
config是 6 位 cron 表达式(秒 分 时 日 月 周),比如"0 */5 * * * *"表示每 5 分钟执行一次 - 阿里云 uniCloud 要求最小间隔 ≥ 60 秒,填
"* * * * * *"会报InvalidTimingTriggerConfig - 改完
package.json后必须右键该云函数 →「上传并部署:云端安装依赖」,否则配置不生效
本地无法模拟定时触发,只能靠日志和真实时间验证
你在 HBuilderX 里点「运行到云函数」或执行 uniCloud.callFunction({ name: 'scheduledTask' }),只是手动调用,和定时触发完全无关。它不会提前跑、也不会按 cron 执行——那只是普通函数调用。
要确认定时是否真在跑,唯一可靠方式是看云函数日志:
- 进 uniCloud Web 控制台 → 对应服务空间 →「云函数」→ 找到你的函数 → 点「日志」
- 等实际触发时间过去后(比如你设了凌晨 2 点,就第二天上午去看),查是否有新日志条目
- 日志里出现
定时任务触发时间: Thu Jun 19 2026 02:00:00 GMT+0800这类输出,才算成功
冷启动延迟常见(首次触发可能慢 1–3 秒),别刚过整点就刷新日志;也别依赖前端 console,云函数日志只存在控制台里。
不能直接在前端调用定时函数来“手动触发一次”,但可以另建一个同逻辑的手动函数
有人想测试逻辑,就写个按钮调用 uniCloud.callFunction({ name: 'scheduledTask' }),结果发现数据没变、也没报错——因为函数本身没问题,只是你误把“定时函数”当成了“可手动调用函数”。其实两者可以共存,但推荐拆开:
- 保留
scheduledTask专用于定时触发(package.json里带trigger) - 再新建一个
runNowTask,逻辑和scheduledTask完全一样,但package.json不配trigger - 前端测试时调
runNowTask,上线后让scheduledTask自动跑
这样避免误操作影响定时节奏,也方便灰度验证。别图省事复用同一个函数名去“凑合试”,容易混淆触发来源和执行上下文。
支付/订单类场景慎用纯定时轮询,优先考虑事件驱动+延迟检查
比如“每小时查一次超时未支付订单”,看似合理,但若订单量大、查询条件没加索引,会拖慢数据库、增加费用。更稳妥的做法是:用户下单时,往订单表写入 scheduledAt: Date.now() + 3600000;再部署一个每分钟跑一次的轻量函数("0 * * * * *"),只查 scheduledAt <= now 的少量记录做更新。
这种模式的优势:
- 避免全表扫描,
scheduledAt字段可建索引 - 响应更及时(分钟级而非固定整点)
- 失败重试友好(下次分钟循环还能捞到)
- 比“每小时扫全表”更省资源,尤其在低峰期
真正复杂的业务逻辑(比如退款回调校验、多系统对账),不要堆在单个定时函数里硬扛,拆成小函数 + 云数据库状态字段 + 异步队列(如 uniCloud 消息队列)才是长期可维护的路径。


















