如何与CoffeeScript重新同步setTimeout()?滑轨5

时间:2019-02-22 22:53:52

标签: javascript ruby-on-rails ruby ajax coffeescript

我为AJAX通知代码开发了一份咖啡脚本。代码本身可以正常工作。我遇到的问题是,我决定使用 setTimeout()而不是 setInterval()来避免耗尽线程并导致严重的拥塞。我很少用过coffeescript,我需要帮助弄清楚如何正确地循环setTimeout函数。在setTimeout使用 getNewNotifications()方法成功接收数据之后,如何调用递归方法调用?

notifications.coffee

class Notifications
  constructor: ->
    @notifications = $("[data-behavior='notifications']")

    if @notifications.length > 0
      @handleSuccess @notifications.data("notifications")
      $("[data-behavior='notifications-link']").on "click", @handleClick

    setTimeout (=>
      @getNewNotifications()
    ), 5000

  getNewNotifications: ->
    $.ajax(
      url: "/new_notification_check.json"
      dataType: "JSON"
      method: "GET"
      success: @handleSuccess
    )

  handleClick: (e) =>
    $.ajax(
      url: "/notifications/mark_as_read"
      dataType: "JSON"
      method: "POST"
      success: ->
        $("[data-behavior='unread-count']").text(0)
    )

  handleSuccess: (data) =>
    items = $.map data, (notification) ->
      notification.template

    unread_count = 0
    $.each data, (i, notification) ->
      if notification.unread
         unread_count += 1

    $("[data-behavior='unread-count']").text(unread_count)
    $("[data-behavior='notification-items']").html(items)

jQuery ->
  new Notifications

2 个答案:

答案 0 :(得分:2)

我相信您应该能够向setTimeout添加handleSuccess,这将创建您要查找的递归调用:

notifications.coffee

class Notifications
  constructor: ->
    @notifications = $("[data-behavior='notifications']")

    if @notifications.length > 0
      @handleSuccess @notifications.data("notifications")
      $("[data-behavior='notifications-link']").on "click", @handleClick

    setTimeout (=>
      @getNewNotifications()
    ), 5000

  getNewNotifications: ->
    $.ajax(
      url: "/new_notification_check.json"
      dataType: "JSON"
      method: "GET"
      success: @handleSuccess
    )

  handleClick: (e) =>
    $.ajax(
      url: "/notifications/mark_as_read"
      dataType: "JSON"
      method: "POST"
      success: ->
        $("[data-behavior='unread-count']").text(0)
    )

  handleSuccess: (data) =>
    items = $.map data, (notification) ->
      notification.template

    unread_count = 0
    $.each data, (i, notification) ->
      if notification.unread
         unread_count += 1

    $("[data-behavior='unread-count']").text(unread_count)
    $("[data-behavior='notification-items']").html(items)

    setTimeout (=>
      @getNewNotifications()
    ), 5000        

jQuery ->
  new Notifications

答案 1 :(得分:0)

尽管您可能必须转换JS输出以使其与浏览器兼容,但这可以使用promises / async / await更加干净地完成。

在下面的示例中可以看到抽象方法。

test = ->
  for i in [1,2,3]
    await new Promise (resolve, reject) ->
      setTimeout ->
        console.log(i)
        resolve()
      , 1000

# run asynchronously
setTimeout test

console.log("async loop is running")

运行此脚本将按顺序打印每个数字,每个数字之间有1秒的延迟,然后退出。

就您的代码而言,没有什么不同。 $.ajax支持异步/等待(guide),因此您可以将getNewNotifications方法更改为此

getNewNotifications: ->
  await $.ajax(
    url: "/new_notification_check.json"
    dataType: "JSON"
    method: "GET"
  )

以及构造函数中对此的调用:

setTimeout =>
  loop
    await new Promise (resolve, reject) =>
      setTimeout =>
        results = await @getNewNotifications()
        @handleSuccess(results)
        resolve()
      , 5000

这很好,因为它消除了对回调或递归的需求