5

我有一个使用标头 ETag 的服务器。Backbone 首次引用 API:一切正常,响应接收并解析。第二次:主干向服务器发送 ETag,作为响应收到 NotModified。并且 Backbone 试图解析这个响应,从而产生一个名为 reset 的集合。

有什么办法可以重置收藏吗?

在 fetch 方法中添加添加选项的方法将不起作用。由于我需要完全刷新集合,如果我来到服务器的响应。

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'),
            }
        });
    }
4

2 回答 2

8

据我所知,没有简单的解决方案来捕获 304 响应。我想出了什么:

  • parse接收第二个参数options您可以使用它来检查请求的状态,并在必要时使用相同的模型重新填充您的集合。它有效,但它会触发一个reset

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

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

  • jQuery 接受一个ifModified可以帮助你的选项

    ifModified 默认值:false

    仅当自上次请求以来响应已更改时,才允许请求成功。这是通过检查 Last-Modified 标头来完成的。默认值为 false,忽略标题。在 jQuery 1.4 中,此技术还检查服务器指定的“etag”以捕获未修改的数据。

  • 或覆盖fetch函数以停止 304 响应

    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/

于 2012-06-20T08:44:52.117 回答
1

304 响应不能包含消息体。抱歉,太着急回答了,我的话在这里没有用。

于 2012-06-20T10:57:04.910 回答