在Backbone.js中处理REST API“创建”响应的最佳方法是什么

时间:2011-05-21 13:15:26

标签: rest backbone.js

我正在使用backbone.js与REST API交互,当发布到它创建新资源时,响应状态为201,“Location”标头指向资源的URI,但是空体

当我创建一个新模型时,它成功了,但模型的本地表示只包含我明确设置的属性,而不包含将在服务器上设置的任何属性(created_date等)< / p>

根据我的理解,Backbone将使用正文中的数据更新其模型的表示形式(如果有的话)。但是,既然没有,它就没有。

所以,显然,我需要使用Location标头中的位置来更新模型,但是最好的方法是什么。

我目前的心态是我必须从头部解析url,拆分id,设置模型的id,然后告诉模型fetch()。

这看起来非常混乱。有更清洁的方法吗?

我对API有一些影响。是尝试让API作者将新模型作为响应主体返回的最佳解决方案(保留201和位置标题)?

谢谢!

3 个答案:

答案 0 :(得分:7)

听起来你必须做一点定制。 也许重写继承自的模型类的p​​arse方法和url方法 Backbone.Model。

继承的功能是:

url : function() {
  var base = getUrl(this.collection);
  if (this.isNew()) return base;
  return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},
parse : function(resp) {
  return resp;
},

你可以尝试类似的东西:

parse: function(resp, xhr) {
    this._url = xhr.getResponseHeader('location')
    return resp
}
url: function() {
    return this._url
}

答案 1 :(得分:5)

是的,backbone.js真的希望保存(可以是PUT或POST)的结果是一个可解析的主体,可用于更新模型。如果,如您所说,您对API有影响力,您应该看看是否可以安排内容正文包含资源属性。

正如您所指出的那样,进行第二次线上调用以完全实现模型毫无意义。

状态代码200可能更合适。纯粹主义者可能认为201状态代码意味着只返回一个位置而不是实体。显然,在这种情况下这没有意义。

答案 2 :(得分:2)

使用Backbone 0.9.9,我无法获得接受的工作答案。 parse函数的签名似乎在旧版本中已更改,并且函数签名中不再提供xhr对象。

这是我所做的一个例子,它使用Backbone v0.9.9和jQuery 1.8.3(使用Deferred Object/Promise),依赖于{{3}返回的jqXHR object }:

window.CompanyView = Backbone.View.extend({
// ... omitted other functions...

    // Invoked on a form submit
    createCompany: function(event) {
        event.preventDefault();
        // Store a reference to the model for use in the promise
        var model = this.model;
        // Backbone.Model.save returns a jqXHR object
        var xhr = model.save();
        xhr.done(function(resp, status, xhr) {
            if (!model.get("id") && status == "success" && xhr.status == 201) {
                var location = xhr.getResponseHeader("location");
                if (location) {
                    // The REST API sends back a Location header of format http://foo/rest/companys/id
                    // Split and obtain the last fragment
                    var fragments = location.split("/");
                    var id = fragments[fragments.length - 1];
                    // Set the id attribute of the Backbone model. This also updates the id property
                    model.set("id", id);
                    app.navigate('companys/' + model.id, {trigger: true});
                }
            }
        });
    }
});

我没有使用可以在success函数提供的options哈希中指定的Backbone.Model.save回调,因为在收到XHR响应之前会调用该回调。也就是说,存储对jqXHR对象的引用并在success回调中使用它是没有意义的,因为当回调为jqXHR时,Backbone.sync将不包含任何响应头。调用

另一个解决此问题的方法是编写自定义{{1}}实现,但我不喜欢这种方法。