setInterval()函数让Node.js进程保持运行状态

3

我正在用CoffeeScript编写类似令牌桶的东西。

class TokenBucket
  constructor: (@speed, @threshold) ->
    @currentVolume = 0
    @interval = setInterval =>
      @currentVolume += 1
      if @threshold < @currentVolume
        @currentVolume = @threshold
    , @speed * 1000

  stop: ->
    clearInterval @interval
    return

  get: ->
    if @currentVolume == 0
      false
    else
      @currentVolume -= 1
      true

对于不熟悉CoffeeScript的人,让我简单解释一下。在构建TokenBucket之后,它会调用setInterval并设置一个回调函数,每隔几秒钟就会增加“桶”的容量。
问题是,如果用户在退出之前忘记调用stop,那么setInterval将会保持Node.js进程运行,因为事件循环永远不会为空。我想做的是告诉Node.js这个setInterval不重要,如果其他所有事情都完成了,你可以终止它。我该如何实现呢?

你能描述一下节点应该“看到”什么,或者在没有用户发起“停止”调用的情况下,节点会发生什么代码路径终止进程吗? - Mike 'Pomax' Kamermans
我想做的是告诉Node.js这个setInterval不重要。在这个上下文中,“重要”是什么意思? - Ram
为什么在“其他所有事情都完成时”不自己调用clearInterval呢? - meskobalazs
@Mike'Pomax'Kamermans 最好停止在setInterval()中执行回调并退出。 - Hot.PxL
@Vohuman 这个意思是说这只是一个协程,如果其他所有人都在事件循环中完成了,那么停止再次执行它。 - Hot.PxL
@meskobalazs 那真的很好。但有时我会忘记。我实际上正在为库构建一个模块。所以不能指望用户那么遵守规范。如果能自动完成这个过程就太好了。 - Hot.PxL
1个回答

9
我希望做的是告诉Node.js,这个setInterval不重要,如果所有其他操作都完成了,可以终止它。我该如何实现?
您需要使用unref方法,该方法“允许您创建一个活动计时器,但如果它是事件循环中唯一剩下的项目,则不会使程序持续运行。”。
class TokenBucket
  constructor: (@speed, @threshold) ->
    …
    @interval = setInterval =>
      …
    , @speed * 1000
    @interval.unref()

然而,我想知道这是否是最佳解决方案。也许更好的做法是将@currentVolume变成一个getter,在需要时动态计算它的值(取决于当前时间)。就像这样:

class TokenBucket
  constructor: (@speed, @threshold) ->
    @_start = Date.now()

  Object.defineProperty @::, "currentVolume",
    enumerable: true,
    configurable: true,
    get: ->
      dt = (Date.now() - @_start) / 1000
      Math.min @threshold, Math.floor dt/@speed

  get: ->
    if @currentVolume == 0
      false
    else
      @_start = Math.max @_start, Date.now()-@threshold*@speed*1000 # not 100% accurate
      @_start += @peed*1000
      true

谢谢。这正是我要找的。另外,我同意你的观点,最好在需要时计算它的值。这涉及到上次查询的时间戳等,对吧? - Hot.PxL
@Hot.PxL:是的,没错。虽然get()的减少使它变得有点复杂,但我不知道你的确切用例/问题域,所以你可能需要/想要稍微调整一下,但我猜你会想出来的。 - Bergi
我已经使用Nodejs多年了,以前从未见过这个函数。太棒了。 - Mike 'Pomax' Kamermans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接