Ajax Coffeescript 中的轮询 - 什么超出了范围,为什么?

Ajax polling in Coffeescript - whats falling out of scope and why?

当后台工作人员缓存了生成预览所需的图像(这可能需要一些时间)时,我想重新加载 iframe。

class Preview
  constructor: (preview) ->
    @preview = preview
    @loadWhenCachedPoll() unless @preview.data?.footprintsCached?

  loadWhenCachedPoll: ->
    @interval = null
    @interval = setInterval(@loadWhenCached(), 3000)

  loadWhenCached: ->
    console.log "polling"
    $.ajax(
      url: "/user_image_caches/cached",
      method: "GET"
      dataType: "JSON"
      success: (data) =>
        if data["cached"] == "true"
          clearInterval(@interval)
          @preview.data.footprintsCached.val("true")
          @preview.attr('src', '/certificate.pdf')
    )

jQuery ->
  new Preview $("[data-behavior='preview']")

第一次运行成功,之后每次都运行成功 Uncaught SyntaxError: Unexpected identifier

表明某些事情超出了范围。

我的粗略猜测是您在 setInterval 中丢失了 "this" 绑定,因为 setInterval 发生在 window 上。我会在 setInterval 内的匿名函数中抛出一个 console.log 来检查 'this',或 bind/wrap @loadWhenCached()。不过,我已经有一段时间没有使用 coffeescript 了,所以可能是 '@' 造成的。

你有两个错误:

  1. 您正在使用 loadWhenCached 的 return 值而不是 loadWhenCached 函数本身调用 setInterval
  2. loadWhenCached 不绑定任何东西,因此 this 不会是您在 setInterval 调用它时所期望的那样。

第一个很容易修复,传递函数引用而不是调用函数:

setInterval(@loadWhenCached, 3000) # No function-calling parentheses

您的版本在构建 setInterval 的参数列表时调用 loadWhenCached,而不是被 setInterval 调用。

第二个可以通过多种方式修复。您可以使用 fat-arrow:

使 loadWhenCached 成为绑定方法
loadWhenCached: =>
  #...

或者您可以在调用 setInterval:

时使用 Function.prototype.bind 绑定它
setInterval(@loadWhenCached.bind(@), 3000)