this.each not iterating through collection correct

2019-04-14 01:50发布

问题:

I've just started using backbone.js and I'm adding some basic methods to extend a collection allowing me to iterate through a collection and save all models, and iterate through a collection to destroy all models. I realise that bulk updates aren't RESTful, but I'm only updating to local storage so didn't think it would be an issue to do multiple updates.

In my base application, the collection has 9 models. When I call collection.saveModels() it correctly logs the length of the collection, and correctly saves all the models.

When I call collection.deleteModels() it correctly logs the length of the collection, but skips every second model (i.e. the 2nd, 4th, 6th, 8th). Each time delete is pressed it continues to only delete the odd indexed element, with the last item to be deleted being the 8th original item.

Is it possible I'm using the each function incorrectly, despite it working perfectly when I save?

_.extend(Backbone.Collection.prototype, Backbone.Events, {
saveModels  :   function() {
    console.log(this.length);
    this.each(function(model){
        console.log('saving model ' + model.get('name'));
        model.save();
    });
},
deleteModels    :   function() {
    console.log(this.length);
    this.each(function(model){
        console.log('deleting model ' + model.get('name'));
        model.destroy();
    });
}
});

and they are called like so: mycollection.saveModels(); and mycollection.deleteModels();

I realise I can iterate through the collection based on length, but I'd rather use the built in method where possible.

回答1:

The code bradgonesurfing posted doesn't actually work as the clone method doesn't return an underscore object. The correct way is to use the _.chain method with makes each method chainable.

_.chain(App.articles.models).clone().each(function(model){
  console.log('deleting model ' + model.get('name'));
  model.destroy();
});


回答2:

The code below worked great for me:

  destroyAll: function (options) {
    while (this.models.length > 0) {
        this.models[0].destroy(options);
    }    
}


回答3:

Every time you call model.destroy() it removes itself from the collection. The each iterator doesn't know this. Do something like the following.

_.chain(App.articles.models).clone().each(function(model){
  console.log('deleting model ' + model.get('name'));
  model.destroy();
});

Backbone has access to underscore.js utils. First clone the models array then iterate over that and then destroy each model. Should work



回答4:

This is the implementation of kinakuta's comment I ended up using.

destroy_models  :   function() {
    for (var i = this.length - 1; i > -1; i -=1){
        this.getByCid('c'+i).destroy();
    }
}