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

如何用Async Await实现Node.js脚本每6小时自动运行

Instagram生日倒计时自动更新简介解决方案

问题概述

现有基于instagram-private-api的Node.js异步脚本,功能为计算生日倒计时并更新Instagram个人简介,需要实现每6小时自动运行。尝试node-cron时出现未捕获Promise异常,同时拥有Heroku账号,寻求可行部署方案。

原脚本代码:

const { IgApiClient } = require("instagram-private-api")
const ig = new IgApiClient()

const USERNAME = "abc"
const PASSWORD = "xyz"

ig.state.generateDevice(USERNAME)
const main = async () => {
    var birthday = new Date(2069, 05, 14);
    var today = new Date();
    birthday.setFullYear(today.getFullYear());
    if (today > birthday) {
    birthday.setFullYear(today.getFullYear() + 1);
    }
    var daystill = Math.floor((birthday - today) / (1000*60*60*24))

    await ig.simulate.preLoginFlow()
    await ig.account.login(USERNAME, PASSWORD)
    process.nextTick(async () => await ig.simulate.postLoginFlow())
    await ig.account.setBiography(`${daystill} Days till my Birthday, Today is ${new Date().getDate()}/${new Date().getMonth()}/${new Date().getFullYear()}. (AutoGenerated)`)
}
main()

使用node-cron时的报错:

node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);

测试用node-cron代码:

cron.schedule('* * * * *', () => { // this is not every 6hrs
    const main = async () => {
       //same as above
    }
    
    main()
})

报错原因

异步函数main()执行时未捕获Promise异常,且node-cron的回调中直接调用main()未处理错误,导致未捕获的Promise拒绝触发系统报错。

修复后的代码

带node-cron的稳定版本

const { IgApiClient } = require("instagram-private-api");
const cron = require("node-cron");
const ig = new IgApiClient();

// 建议通过环境变量存储账号密码,避免硬编码泄露
const USERNAME = process.env.IG_USERNAME || "abc";
const PASSWORD = process.env.IG_PASSWORD || "xyz";

ig.state.generateDevice(USERNAME);

const main = async () => {
  try {
    // 计算生日倒计时(注意:JavaScript月份为0索引,5代表6月,需根据实际生日调整)
    const birthday = new Date(2069, 4, 14);
    const today = new Date();
    birthday.setFullYear(today.getFullYear());
    if (today > birthday) {
      birthday.setFullYear(today.getFullYear() + 1);
    }
    const daystill = Math.floor((birthday - today) / (1000 * 60 * 60 * 24));

    // 执行IG登录与简介更新
    await ig.simulate.preLoginFlow();
    await ig.account.login(USERNAME, PASSWORD);
    process.nextTick(async () => await ig.simulate.postLoginFlow());
    await ig.account.setBiography(
      `${daystill} Days till my Birthday, Today is ${today.getDate()}/${today.getMonth() + 1}/${today.getFullYear()}. (AutoGenerated)`
    );
    console.log("简介更新完成");
  } catch (error) {
    console.error("任务执行失败:", error);
  }
};

// 配置每6小时执行一次的定时规则(分钟 小时 日 月 周)
cron.schedule("0 */6 * * *", () => {
  console.log("启动定时任务...");
  main();
});

// 脚本启动时立即执行一次
main();

关键修复点

  • 给main()添加try/catch捕获所有异步错误,避免未捕获Promise异常
  • 修正日期月份索引问题:JavaScript的Date对象月份从0开始,原代码的05实际对应6月,需根据实际生日调整
  • 改用环境变量存储账号密码,提升安全性,适配Heroku部署
  • 配置正确的cron表达式0 */6 * * *,实现每6小时整点执行

Heroku部署方案

方案1:基于node-cron保持Dyno运行

  1. 在项目根目录创建Procfile,内容为:
    worker: node your-script-filename.js
    
  2. 将代码推送到Heroku仓库后,启动worker dyno:
    heroku ps:scale worker=1
    
  3. 设置环境变量存储IG账号密码:
    heroku config:set IG_USERNAME=你的Instagram账号 IG_PASSWORD=你的Instagram密码
    
  4. 注意:Heroku免费Dyno每日会休眠6小时,可能导致定时任务遗漏,若需稳定运行可考虑升级付费Dyno。

方案2:使用Heroku Scheduler(适合免费用户)

无需保持Dyno持续运行,通过Heroku定时触发脚本:

  1. 整理脚本为独立执行文件(如update-bio.js),移除node-cron相关代码,在脚本末尾添加:
    main().catch(err => console.error(err));
    
  2. 在Heroku控制台启用"Scheduler"插件,添加定时任务:
    • 频率选择Every 6 hours
    • 命令输入node update-bio.js
  3. 同样通过Heroku配置环境变量存储账号密码。

内容的提问来源于stack exchange,提问作者JazzTGB145

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:35:18