对于真正的长期计时器,您需要以某种方式将超时数据存储在磁盘上。正如您所提到的,如果您纯粹在内存中执行此操作,那么如果服务器重新启动,您将丢失时间信息。
处理这个问题的方法很简单。这与 cron 使用的算法相同:
记录您希望何时在磁盘上发生超时 - 格式由您决定,您可以使用 cron 格式或发明自己的格式。由于它是 javascript,我很想简单地以 JSON 格式记录。
将时序文件读入您的程序。有两种方法可以做到这一点。如果您担心运行时性能,请在程序启动时阅读一次。但是,这意味着如果您编辑文件,则需要重新启动服务器。如果您希望自动获取文件的更新,请在每次要处理计时事件时读取它。
定期运行计时器循环。例如,Cron 的分辨率为一分钟。因此 cron 每分钟运行一次计时器循环。如果这比每分钟运行一次足够好。对我来说,我会setInterval()
每 30 秒左右做一次。请注意,在任何体面的处理器上,每秒运行一个计时器循环在 javascript 中并不是那么繁重。
在定时器循环中处理来自文件的定时器事件。循环遍历所有事件并检查它们是否已过期。
就是这样。这就是所有调度系统的工作方式(谷歌日历、cron 等)。
这是一个非常简单的javascript实现:
var events = require("events.js");
// Assume events.js look something like:
// return [ {
// timeout: <millisecs like what Date.now() returns>,
// callback: <function>
// } ]
setInterval(function(){
var now = Date.now();
events.forEach(e=>{
if (e.timeout >= now) {
e.callback(); // execute event
}
});
events = events.filter(e=>e.timeout<now); // remove stale events
},10000); // every 10 seconds
如果代码有任何更改,您可以添加花哨的功能,例如将当前事件保存到磁盘,使超时格式便于调试,定义系统以将参数传递给事件回调等。但核心非常简单。