Использование наблюдателей Ember с синхронизированной очисткой очереди

Я пытаюсь создать своего рода «систему уведомлений» для наложения вещания. По сути, я ловлю события, добавляю их в массив, а затем запускаю функцию, которая наблюдает за этим массивом. Каждый раз, когда добавляется событие, я запускаю анимацию, которая занимает заданное количество времени, удаляю ее из массива и затем перехожу к следующей.

Я обнаружил, что debounce помогает мне в этом. Я могу добавить любое количество событий во время выполнения анимации, и это может очистить очередь.

Проблема в том, что я должен ждать указанное время (в данном случае 5 секунд), прежде чем будет обработано первое событие. Однако, когда я устанавливаю немедленное отключение, все прерывается тем, что первое событие будет немедленно обработано, но больше ничего не будет.

# Pool handling.
pool: []

# Function adds events to the pool array.
addEventToPool: (event, data) ->
  console.log "added #{event} with #{data} to pool!"
  @get('pool').pushObject(data)

# Function that observes the pool array and runs debounce 
# if there are any items in the pool.
observePool: (->
  Ember.run.debounce(@, @handleEvent, 5000, false) if @get('pool').length
).observes('pool.[]')

# Event handling.
handleEvent: ->
  pool = @get('pool')
  object = pool.get('firstObject')
  @set('payload', object)

  Ember.$(".event-message__#{object.event}").addClass('active')

  Ember.run.later (->
    Ember.$(".event-message__#{object.event}").removeClass('active')
    pool.removeObject(object)
  ), 2000

  console.log "Number of remaining objects: #{pool.length}."
  console.log "Objects remaining: #{JSON.stringify pool}."

У меня есть ощущение, что мне нужно уйти с debounce, чтобы исправить это, но я не уверен, что это за решение.

Пожалуйста, дайте мне знать, если вам нужны какие-либо разъяснения!


person Bryan Veloso    schedule 22.04.2015    source источник
comment
С первым событием вы хотите обработать его мгновенно или вы хотите подождать 5 секунд в начальном событии? Или тебе все равно? И, во-вторых, скажем, вы получаете два события, которые обрабатываются в 10:30:10, а затем в 10:30:15 - если ваше третье событие происходит в 10:30:22 (то есть через 7 секунд после второго события) - вы хотите обработать это сразу (в 10:30:22) или вы хотите подождать еще 5 секунд (в 10:30:27)?   -  person jmurphyau    schedule 23.04.2015
comment
Я хочу мгновенно обработать первое событие. Если третье событие произойдет в 10:30:22, то есть после второго события, гипотетически пул будет пуст, поэтому я хотел бы обработать это сразу.   -  person Bryan Veloso    schedule 23.04.2015


Ответы (1)


Ember.run.debounce

Цель Ember.run.debounce состоит в том, чтобы запустить что-то только один раз, если debounce не вызывалось в течение последних X seconds.

Его основное использование для таких вещей, как запуск некоторого типа действия после того, как пользователь закончил печатать, поэтому для каждого символа, который кто-то печатает, вы можете вызвать Ember.run.debounce(handleInput, 1000), и вы можете быть уверены, что независимо от того, сколько раз они нажимают клавишу, ваша функция будет запускается только один раз - после того, как они не нажимали клавишу в течение 1 секунды.

Это также полезно для обработки событий прокрутки — где, скажем, сотни событий прокрутки при прокрутке страницы, но вы хотите выполнить какое-то действие только после того, как прокрутка остановится — вызов debounce сотни раз не запустит его, пока вы не выполните перестал вызывать debounce для значения timeout (например, через 100 мс после последнего события прокрутки в этом случае).

Это кажется немного отличным от того, что вы пытаетесь сделать.

Предлагаемое решение

Я думаю, что вы хотите использовать Ember.run.later. Вы можете объединить все это в одну функцию, которая просто наблюдает за pool.firstObject, поскольку вы всегда извлекаете первый объект и удаляете его, когда закончите.

handleEvent: Ember.observer('pool.firstObject', function() {
  var pool = this.get('pool');
  var obj = pool.get('firstObject');
  if (obj) {
    // add class
    Ember.$(".event-message__#{object.event}").addClass('active');

    // schedule remove class for 2 seconds from now
    Ember.run.later(function() {
      Ember.$(".event-message__#{object.event}").removeClass('active');
    }, 2000);

    // schedule remove object from pool 5 seconds from now
    Ember.run.later(function() {
      pool.removeObject(obj);
      // after you've removed this object (which was firstObject)
      // pool.firstObject will change, and the handleEvent function 
      // will get kicked off again
    }, 5000);

  }
})
person jmurphyau    schedule 22.04.2015