BeforeSend передается в Backbone Fetch, не позволяя инициировать события

У меня есть коллекция Backbone. Я использую fetch для ленивой загрузки сообщений Facebook в модель при инициализации.

https://gist.github.com/2271437

exports.Collection = class Posts extends Backbone.Collection
  initialize: (models, options) =>
    @id = options.id
    @activeDetails = false
    @on "loadDetails", @loadDetails
    @on "detailsLoaded", @logger
    debug "initialized posts"
    @fetch
      beforeSend: () =>
        console.log "about to fetch..."
        @trigger "postsLoading"
      success: (collection, response) => 
        debug "successfully loaded ajax"
        @trigger "postsLoaded"
      error: (collection, response) => @trigger "postsLoadingError"

По какой-то странной причине, когда я пытаюсь инициировать события с помощью обработчика beforeSend, события не запускаются. Я могу вызывать любые функции, но если какие-либо функции попытаются использовать @trigger "eventName", событие никогда не сработает так, как я мог наблюдать. В приведенном выше примере функция console.log работает нормально, но триггер не работает.

Любые идеи? Обработчики успеха и ошибок работают великолепно.


person RandallB    schedule 01.04.2012    source источник


Ответы (1)


Вы вызываете fetch внутри своего метода initialize, поэтому ничто не сможет привязаться к этой коллекции до того, как будут запущены события. Метод initialize вызывается во время создания экземпляра вашей коллекции, и это означает, что вы вызываете fetch до возврата конструктора, но вам нужен экземпляр коллекции, прежде чем вы сможете привязаться к ее событиям.

Рассмотрим что-то похожее на это:

class Posts extends Backbone.Collection
  do_things: ->
    @fetch
      beforeSend: () =>
        console.log "about to fetch..."
        @trigger "postsLoading"
      success: (collection, response) => 
        debug "successfully loaded ajax"
        @trigger "postsLoaded"
      error: (collection, response) => @trigger "postsLoadingError"

Тогда, если вы сделаете это:

p = new Posts
p.on('postsLoading', -> console.log('loading'))     
p.do_things()

вы увидите, что ваше событие postsLoading действительно сработало.

Демонстрация: http://jsfiddle.net/ambiguous/PDeFg/

Мораль этой истории проста:

Не вызывайте fetch внутри вашего конструктора, если вы заботитесь о прослушивателях событий.

person mu is too short    schedule 01.04.2012
comment
Я ТЕБЯ ЛЮБЛЮ. Могу ли я установить время ожидания другой функции в объекте, чтобы ждать тик перед выборкой и по-прежнему иметь преимущества выборки при инициализации объекта? - person RandallB; 02.04.2012
comment
@RandallB: Старый трюк setTimeout(..., 0) внутри initialize должен работать, пока вызывающая сторона связывает свои обработчики событий сразу после создания экземпляра коллекции (и вы, вероятно, захотите задокументировать это поведение). - person mu is too short; 02.04.2012