在一个进程中排队javascript代码

时间:2015-01-12 21:18:38

标签: node.js cron queue task setinterval

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

以下是一个例子:

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

我将这些存储在数据库中并且what脚本是eval来自字符串。我需要一个正确的方向。我在节点世界里从来没有见过这样的东西。

我正在考虑使用hotload并使用文件系统,因此我不需要处理数据库。

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

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

1 个答案:

答案 0 :(得分:1)

不要重新发明轮子。从npm使用cron包。他是纯粹写在js上的(使用bellow的第二个变体)。因此,所有这些任务都将在已经存在的运行过程中发生。例如,您可以像这样创建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的最长时间为2147483647ms(约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);
   }
}