【问题标题】:How can I run a function at a particular point in the future? [closed]我怎样才能在未来的某个特定时间运行一个函数? [关闭]
【发布时间】:2021-10-02 10:44:38
【问题描述】:

我的 API 中有一个计划选项,就像我使用 Expressjs 和 NodeJS 所做的那样。我们的后端使用两个参数(用户 ID 和时间戳)调用此 API。目标是在指定时间(..或几分钟后)删除用户信息(文件夹、文档等)。时间戳可以是从现在起 5 分钟到 2 天。

当它发生时,工作完成并且 API 正在等待另一个调用。该 API 每天可以接收 1000 次调用,因此性能非常重要。将来运行该功能的最佳方式是什么?

async function scheduledAction(userId, timestamp) {
    var actionInFuture = await checkDate(timestamp);
    
    if(actionInFuture) {
        console.log('Action triggered');
    }
}

async function checkDate(timestamp) {
    await new Promise(resolve => {
        setTimeout(resolve, 1000)
    });
    
    // timestamp = 1627311533000
    if(Date.now() >= timestamp) {
        return true;
    } else {
        return checkDate(timestamp);
    }
}

app.get('/action', (req, res) => {
    scheduledAction(req.query.userId, req.query.timestamp);
} 
scheduledAction(req.query.userId, req.query.timestamp);

【问题讨论】:

  • 你听说过setTimeout吗?这将阻止您的代码进行最终导致堆栈溢出的紧密递归 - 除非 v8 具有适当的尾递归 - 您是否在代码中注意到了这个问题?
  • 您没有任何类型的延迟,因此您将不断地处理您的代码。然后,一旦您达到目标时间,您的代码就会运行,然后在服务器重新启动之前它不会再次运行。这是你的意图吗?
  • 哦,并且 Date.now 以毫秒为单位,因此您的触发器设置为 1970 年 1 月 19 日:p 这就是为什么您可能没有遇到太多递归问题(不是堆栈溢出,因为我之前说过)
  • 尝试像这样在 JS 中编写调度程序不会奏效。 Js 是单线程的,所以一旦你阻塞了线程,其他任何东西都不会运行。 SetTimeout 可能会起作用,但不能保证它的执行时间。
  • 您需要以某种方式保存状态。如果您重新启动服务器,您将丢失计时器。

标签: javascript node.js sleep


【解决方案1】:

您可以使用 Node Schedule 包,https://www.npmjs.com/package/node-schedule

例如:

var schedule = require('node-schedule');
const date = new Date(1627309531*1000);

var j = schedule.scheduleJob(date, function(){
        console.log('Action triggered');
});

【讨论】:

  • 这基本上以一种受控的方式使用 setTimout —— 单次拍摄可能有点矫枉过正 :p 但为什么要重新发明轮子! ?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 2016-09-11
  • 2015-02-23
相关资源
最近更新 更多