1

I am trying to trigger one event after a batch of models have been added to a collection via the set method. I overrode the set method, called its parents set method and put a console.log in there, and it seemed to be triggering for every model that was trying to be added into the colleciton.

class MyCollection extends Backbone.Collection
    set: ->
        super
        console.log('set called')

I could not determine why this was happening, but to move forward I decided to use underscores debounce method to group these together and fire an event afterwards. This is what I came up with

class MyCollection extends Backbone.Collection
    initialize: ->
        @batchComplete = _.debounce(@_batchComplete, 1000)
        super
        @

    _batchComplete: =>
            if not window.test
                    window.test = @

            if window.test is @
                    console.log 'SAME AS PREVIOUS'
            else
                    console.log 'DIFFERENT', window.test, @

            window.test = @ 
            @trigger('setComplete')

    set: ->        
            super
            @batchComplete()
            @

I have created an instance of this collection and trying to use the set method

c = new MyCollection
c.set([{...},{...},{...}])    

My expectation of this was for window.test to equal @ however they seem to be referencing different locations. This is a sample output in the console

> DIFFERNT MyCollection, MyCollection
> DIFFERNT MyCollection, MyCollection

I dont understand why window.test is not the same as @. As a result of each iteration not being the same, it means that it is not calling the same debounce method

4

1 回答 1

0

If you're really calling set on an empty collection then you could use reset instead:

reset collection.reset([models], [options])

Adding and removing models one at a time is all well and good, but sometimes you have so many models to change that you'd rather just update the collection in bulk. Use reset to replace a collection with a new list of models (or attribute hashes), triggering a single "reset" event at the end.

So you could:

c = new MyCollection
c.on('reset', (collection) -> ...)
c.set([{...},{...},{...}])

and you'd get one 'reset' event at the end.

Demo: http://jsfiddle.net/ambiguous/EVxM7/

If reset isn't appropriate then you could use _.after:

after _.after(count, function)

Creates a version of the function that will only be run after first being called count times.

So you could do things like this:

a = array_of_models
c = new Collection
c.on('add', _.after(a.length, (model, collection) -> ...)
c.set(a)

Demo: http://jsfiddle.net/ambiguous/6SnSS/

You could also override set and trigger a custom event and listen for that custom event to know when set has done its work:

class C extends Backbone.Collection
    set: ->
        super
        @trigger('batch-done', @)

c = new C
c.on('batch-done', (collection) ->
    console.log('All done', collection.toJSON())
)
c.set([ ... ])

Demo: http://jsfiddle.net/ambiguous/YytvS/

于 2013-09-18T06:24:26.633 回答