9

关于 nodejs 计时器的文档说 setTimeout 将返回一个 timeoutId http://nodejs.org/api/timers.html#timers_cleartimeout_timeoutid

当我在网络浏览器中使用 javascript 时,我会得到一个整数作为返回值。

var b = setTimeout(function(){console.log("Taco Bell")})
// b = 20088

当我使用节点并做同样的事情时,回报是

var b = setTimeout(function(){console.log("Taco Bell")})
// { _idleTimeout: 60000,
//   _idlePrev: 
//     { _idleNext: [Circular],
//       _idlePrev: [Circular],
//       ontimeout: [Function] },
//   _idleNext: 
//     { _idleNext: [Circular],
//       _idlePrev: [Circular],
//       ontimeout: [Function] },
//   _onTimeout: [Function],
//   _idleStart: Wed Jan 30 2013 08:23:39 GMT-0800 (PST) }

我想做的是将 setTimeout 整数存储到 redis 中,然后再将其清除。所以我尝试做这样的事情

var redis = require('redis');
var redisClient = redis.createClient();
var delay = setTimeout(function(){console.log("hey")}, 20000);
var envelope  = { 'body' : 'body text', 'from' : 'test@test.com', 'to' : 'test@test.com', 'subject' : 'test subject', 'delay' : delay };
redisClient.hset("email", JSON.stringify(envelope), redis.print);

但后来我从 JSON.stringify 收到一个关于无法处理圆形对象的错误。有没有办法让 setTimeout 返回 ID 或将足够的对象存储到 redis 以便以后清除?

4

3 回答 3

2

我真的不相信在 nodejs 中(我非常喜欢)你会被迫制作这样的功能。

幸运的是,在 setTimeout 的 return(setInterval 也有它!)上有一个未记录的方法,称为close

var timer = setInterval(doSomething, 1000);
setTimeout(function() {
    // delete my interval
    timer.close()
}, 5000);

希望有用

于 2013-10-08T16:17:54.330 回答
1

我将对 setTimeout 的调用包装到一个函数中,该函数将 setTimeout 的结果存储在一个对象中,这样您就可以通过它们的 ID 检索超时。

像这样的东西:

var timeouts = {};
var counter = 0;

function setTimeoutReturnsId(callback, delay) {
  var current = counter++;
  timeouts[current] = setTimeout(function() {
      timeouts[current] = null;
      callback();
    }, delay);
  return current;
}

function getTimeoutFromId(id) {
  return timeouts[id];
}

当然,当你的节点服务器重启时,你需要清除 redis。

于 2013-01-30T20:18:42.157 回答
0

一直在努力解决这个问题,所以这里有一个现代的技巧:

在最新版本的节点中,节点计时器为此使用符号;计时器对象具有三个符号键。我需要将计时器的唯一 ID 添加到我的开发调试日志中,但是当我没有计时器系统的该字段的私有符号时,在句柄的映射中查找该字段是一个障碍。

(如果我在生产中需要易于打印的 id,那么在接受的答案中实现整个外观是我这样做的唯一方法;但是构建该外观只是为了调试一些棘手的计时器交互并再次将其撕掉是太多的突变我正在尝试调试的非常代码。)

我发现的唯一 kludge 是使用 util.inspect 对 unstringable 进行字符串化,并且由于我只保持 kludge 足够长的时间来调试我当前的模块,所以我不担心另一个具有相同描述性字符串的符号潜入从发布或添加其他库:

function getId(timer) {
    var ids = Object.getOwnPropertySymbols(timer); // this currently returns three symbols
    var key;
    ids.forEach(id => {
        if (util.inspect(id) === 'Symbol(triggerId)') key = id;
    });
    if (!key) throw new Error('Symbol(triggerId) not found in timer');
    return timer[key];
}
于 2020-04-25T20:59:29.717 回答