Working with api responses in backbone.js using parse

One backbone.js behavior that was kind of upsetting me recently is the fact that it re-syncs your model after you save it on the server.

You know, you just set a model you changed, save it on the server in the background and continue your day in your application. Backbone however awaits patiently the response from the server api, and if the response does not correspond with your current model state, it sets the response attributes back to your model.

That’s very nice of backbone, but what happens if your response also contains other data? You don’t want non relevant data to be set in your model, and that’s a bummer.

Before starting I need to say that I had access to the api and made modification to it, if you just plug on a 3rd party API, this is going to be a bit harder.

Hello parse

One thing very nice in backbone is that pretty much anything is over writable. The function that re-syncs your model is parse, and it is very easy to overwrite in your model definition.

  parse : function(resp, xhr) {
  	return resp;
  },

What you got above is what backbone does with your server response, it checks if the values are the same that your model, and if not it just returns it to the model so it can be updated.

How one goes to stop that? not really hard:

  parse : function(resp, xhr) {
 
  },

Now your model is never updated after your server response.

Oups

Now you can’t get anything from the server, not really useful when you try to get a collection from the server, to that end we will modify the api and return a type of request with the response.

  parse : function(resp, xhr) {
      if(resp.type =="read"){
        return resp;
      }
    },

There you go, when you read data, you will receive your response untouched and backbone should handle the normal process by itself.

Okay, but what about id’s when I create a new model

When you create a new model and save it to your API, you need the new id from the database to be able to edit that model again. If you do not have that id, you can’t tell your api what it needs to edit.

To this end we will have to modify our parse func using the type of action that backbone is doing.

  parse : function(resp, xhr) {
  	if(resp.type && (resp.type =="create")){
  		return {
  			"id": resp.data.id
  		}	
  	}else if(resp.type && (resp.type =="update")){ }else{	
        	return resp;
  	}
   },

As you can see, if the type of request is “create” I return back the id to the model. Then, my only problem is the update action that would set back my response to the model. In the example above, if the type is not update, backbone can go on as normal.

My server response could look something like this:

{
  "status":"success",
  "type":"update",
  "message":"Model as been updated in the database",
  "dataModel":{
    "id":4,
    "name":"This is a model"
  }
}

Using parse on the model and globally

You could always define parse on each model like you would for your url, but generally it is going to be the same code on all your model, so one thing you could do is extend the backbone.js model’s prototype.

 Backbone.Model.prototype.parse = function(resp, xhr) {
  	if(resp.type && (resp.type =="create")){
  		return {
  			"id": resp.data.id
  		}	
  	}else if(resp.type && (resp.type =="update")){ }else{	
        	return resp;
  	}
 }

And there you go!

Cedric Dugas is a front-end veteran with more than 9 years under the belt, between his open source projects & entrepreneurial ambitions he is a product architect at CakeMail. Why don't you follow him on twitter.

Got something to say? Go for it!