Как синхронизировать setTimeout () с CoffeeScript?Рельсы 5 - PullRequest
0 голосов
/ 23 февраля 2019

Я разработал 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 голосов
/ 23 февраля 2019

Это можно сделать чуть более аккуратно, используя promises / async / await, хотя вам, возможно, придется переносить вывод JS для совместимости с браузером.

Абстрактный подход можно увидеть в следующем примере.

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 поддерживает async / await ( 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

Это хорошо, потому что устраняет необходимость в обратных вызовах или рекурсии

0 голосов
/ 23 февраля 2019

Я полагаю, что вы сможете добавить 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
...