在单个进程中排队 javascript 代码

Queue up javascript code in a single process

假设我在一个对象中有一堆任务,每个任务都有一个日期对象。我想知道是否有可能在单个进程中让对象内的任务 运行 并在调用日期时触发。

这是一个例子:

var tasks = [
  "when": "1501121620",
  "what": function(){
    console.log("hello world");
  },
  "when": "1501121625",
  "what": function(){
    console.log("hello world x2");
  },
]

我很乐意将这些存储在数据库中并且 what 脚本是 eval 从字符串编辑的。我需要指出正确的方向。我在节点世界中从未见过这样的事情。

我正在考虑使用 hotload 并使用文件系统,这样我就不需要处理数据库了。

我应该看看 setInterval 还是有更复杂的东西?我知道 cron 之类的东西存在,问题是我需要所有这些任务在一个已经存在的 运行ning 流程中发生。我需要能够在不结束进程的情况下将新任务添加到队列中。

为了添加一点上下文,我需要一些排队 socket.io .emit() 函数的方法。

不要重新发明轮子。使用来自 npm 的 cron 包。他是纯 js 编写的(使用下面的第二个变体)。因此,所有这些任务都将发生在一个已经存在的 运行 流程中。例如,您可以像这样创建 CronJob

var CronJob = require('cron').CronJob;
var job = new CronJob(1421110908157);
job.addCallback(function() { /* some stuff to do */ });

在纯 javascript 中,您只能通过 setTimeoutsetInterval 方法来完成。有两种变体:

1) 设置间隔回调,这将检查您的任务队列并在适当的时间执行回调:

setInterval(function() {
    for (var i = 0; ii = tasks.length; ++i) {
        var task = tasks[i];

        if (task.when*1000 < Date.now()) {
            task.what();
            tasks.splice(i,1);
            --i;
        }
    };
}, 1000);

As you see accuracy of callback calling time will be dependent on interval time. Less interval time => more accuracy, but also more CPU usage.

2) 围绕您的任务创建包装器。因此,当您想要添加新任务时,您正在调用一些方法 addTask,这将通过您的任务回调调用 setTimeout。请注意 setTimeout 的最长时间为 2147483647 毫秒(大约 25 天)。因此,如果您的时间超过了最长时间,则必须使用回调设置最长时间超时,这将设置新的超时时间和剩余时间。例如:

var MAX_TIME = 2147483647;
function addTask(task) {
   if (task.when*1000 < MAX_TIME) {
       setTimeout(task.what, task.when);
   }
   else {
       task.when -= MAX_TIME/1000;
       setTimeout(addTask.bind(null, task), MAX_TIME);
   }
}