setInterval()使Node.js进程保持运行

Hot*_*PxL 3 javascript node.js coffeescript

我在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
Run Code Online (Sandbox Code Playgroud)

对于不熟悉CoffeeScript的人,让我简单解释一下.在构造a之后TokenBucket,它setInterval使用回调来调用,该回调每隔几秒递增一次"桶".

问题是,如果用户忘记stop在现有之前调用,那么setInterval将继续运行Node.js进程,因为事件循环永远不会为空.我想要做的是告诉Node.js这setInterval不重要,如果其他一切都完成,你可以终止它.我怎样才能做到这一点?

Ber*_*rgi 9

我想要做的是告诉Node.js这个setInterval不重要,如果其他一切都完成,你可以终止它.我怎样才能做到这一点?

您正在寻找的unref方法," 将允许您创建一个活动的计时器,但如果它是事件循环中剩下的唯一项目将不会保持程序运行. ".

class TokenBucket
  constructor: (@speed, @threshold) ->
    …
    @interval = setInterval =>
      …
    , @speed * 1000
    @interval.unref()
Run Code Online (Sandbox Code Playgroud)

但是,我想知道这是否是最好的解决方案.可能最好@curretnVolume只在需要时制作一个动态计算其值(取决于当前时间)的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
Run Code Online (Sandbox Code Playgroud)