Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.js parse not-modified response

I have a server that works with a header ETag. Backbone refers to the API for the first time: everything is good, the response received and parse. Second time: backbone sends to the server ETag, in response receives NotModified. And Backbone trying to parse this response, resulting in a collection called reset.

Is there any way around it resets the collection?

The method of adding the option to add in the fetch method will not work. Since I need to completely refresh the collection, if I came to the server's response.

var recommendCollection = Backbone.Collection.extend({
    model : Event,
    etag : null,
    urlRoot : '/api/users',
    initialize: function() {
        this.etag = null;
    },
    parse: function(response) {
        return response.data;
    },      
    url : function () {
        return (this.urlRoot + "/"+window.me.get('id')+ "/recommendation");
    },
    beforeSend : function (jqXHR, settings) {
        jqXHR.setRequestHeader('if-none-match', this.etag);
    },
    complete : function (jqXHR, textStatus) {
        if (jqXHR.status == 200 || jqXHR.status == 304) {
            this.etag = jqXHR.getResponseHeader('ETag');
        }
    },
    update : function () {
        this.fetch({
            beforeSend : this.beforeSend.bind(this),
            complete : this.complete.bind(this),
            data : {
                cityId : window.me.get('cityId'),
            }
        });
    }
like image 488
Anton Tsivarev Avatar asked Jun 20 '12 06:06

Anton Tsivarev


2 Answers

As far as I can tell, there is no easy solution to trap a 304 response. What I came up with:

  • parse receives a second argument, options, that you can use to check the status of the request and repopulate your collection with the same models if necessary. It works, but it will trigger a reset

    parse: function(response, options) {
        if (options.xhr.status === 304)
            return this.models
    
        return response.data;
    }
    

    http://jsfiddle.net/nikoshr/sxv9P/12/

  • jQuery accepts an ifModified option that may help you

    ifModified Default: false

    Allow the request to be successful only if the response has changed since the last request. This is done by checking the Last-Modified header. Default value is false, ignoring the header. In jQuery 1.4 this technique also checks the 'etag' specified by the server to catch unmodified data.

  • Or override the fetch function to stop on a 304 response

    fetch: function(options) {
          options = options ? _.clone(options) : {};
          if (options.parse === undefined) options.parse = true;
          var collection = this;
          var success = options.success;
          options.success = function(resp, status, xhr) {
            if (xhr.status!==304)
                collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
            if (success) success(collection, resp);
          };
          options.error = Backbone.wrapError(options.error, collection, options);
          return (this.sync || Backbone.sync).call(this, 'read', this, options);
    }
    

    http://jsfiddle.net/sxv9P/1/

like image 118
nikoshr Avatar answered Sep 28 '22 14:09

nikoshr


The 304 response MUST NOT contain a message-body. Sorry, was too hurry answering, my words don't help here.

like image 23
Yaroslav Avatar answered Sep 28 '22 15:09

Yaroslav