PATCH request method in Backbone.js

2019-03-18 02:26发布

问题:

What is the right way to perform PATCH request while saving model's attributes in Backbone.js?

回答1:

As of Backbone.js v0.9.9, you can simply pass { patch: true } to save().

Read more: http://backbonejs.org/#changelog



回答2:

In addition to James Cropchos answer I want add the following, because this steals some hours from me and maybe helps someone else:

If you use model.save(attributesToPatchObject,{patch: true}) like it is possible since backbone v.0.9.9 as stated in James Cropchos answer, you may wonder how to determine which attributes have changed since the last call of model.save() to pass them in as attributesToPatchObject which is the first argument from model.save() (or model.fetch() if you didn't save the model lately).

Backbone itself didn't keep track of those attributes. I thought the method model.changedAttributes() could fit, but as the backbone-doc says this method returns

a hash of only the model's attributes that have changed since the last set, or false if there are none

So this method didn't fit for this need. After some research I found out that backbone itself didn't keep track of unsaved attributes (I know, not a brilliant finding if I had read the docs more carefully).

I found out that backbone.trackit is a backbone plugin which exactly add the needed feature to backbone, by adding the method unsavedAttributes() to the model. The docs of backbone.trackit says about this method:

Symmetric to Backbone's model.changedAttributes(), except that this returns a hash of the model's attributes that have changed since the last save, or false if there are none. Like changedAttributes, an external attributes hash can be passed in, returning the attributes in that hash which differ from the model.

It works like this:

//fetch an existing model from server
model.fetch({
  success : function(model, respose, options) {
    //tell backbone.trackit to track unsaved Attributes
    model.startTracking();
  }
});

//now some changes to the model happen
model.set("someProperty", "someValue");

/* save the model to server using the PATCH-Method 
   and only send the unsaved Attributes; 
   in this case only "someProperty" is sent
*/
model.save(model.unsavedAttributes(), {patch: true});

Since the unsavedAttributes() returns false if there are no unsaved Attributes, you could additionally wrap your save() statement within an if-condition which checks if unsavedAttributes() returns something other then false and only do your PATCH-Request if it's needed (because something changed).

NOTE: You didn't have to call fetch() to use startTracking() so you can use this method even with newly created models (model.isNew() returns true on that model), if there is a usecase for that.

Hopes this may save someone a little bit of research time.



回答3:

You'll have to override Backbone.sync and extend the existing method mapper

var methodMap = {
    'create': 'POST',
    'update': 'PUT',
    'delete': 'DELETE',
    'read':   'GET',
    'patch':  'PATCH'
};

you'll have to create your own patch method on a model like

Backbone.Model.prototype.patch = function(options) 
{
    // some code here that checks what attributes have changed since last save
    var xhr = (this.sync || Backbone.sync).call(this, 'patch', this, options);
    return xhr;  
}

I'm sure you can extend Backbone further to include OPTIONS and HEAD if you needed to

Note though, that even through jQuery supports the PATCH, OPTIONS and HEAD methods, your end-users' browser may not.