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

发布于 2024-11-09 12:55:19 字数 475 浏览 0 评论 0原文

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

当我现在创建一个新模型时,它成功了,但是模型的本地表示仅包含我显式设置的属性,而不包含将在服务器上设置的任何属性(created_date等)

据我所知,Backbone 将使用主体中的数据(如果有的话)更新其模型的表示。但是,既然没有,那就没有。

因此,显然,我需要使用 Location 标头中的位置来更新模型,但执行此操作的最佳方法是什么。

我目前的想法是,我必须解析标头中的 url,拆分出 id,设置模型的 id,然后告诉模型进行 fetch()。

这看起来真的很混乱。有没有更干净的方法来做到这一点?

我对 API 有一定的影响力。尝试让 API 作者返回新模型作为响应正文(同时保留 201 和位置标头)的最佳解决方案是吗?

谢谢!

I'm using backbone.js to interact with a REST API that, when posting to it to create a new resource, responds with a status of 201, a 'Location' header pointing to the resource's URI, but an empty body.

When I create a new model at the moment, its successful, but the local representation of the model only contains the properties I explicitly set, not any of the properties that would be set on the server (created_date, etc.)

From what I understand, Backbone would update its representation of the model with data in the body, if there were any. But, since there isn't, it doesn't.

So, clearly, I need to use the location in the Location header to update the model, but what's the best way to do this.

My current mindset is that I would have to parse the url from the header, split out the id, set the id for the model, then tell the model to fetch().

This seems really messy. Is there a cleaner way to do it?

I have some influence over the API. Is the best solution to try to get the API author to return the new model as the body of the response (keeping the 201 and the location header as well)?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海之角 2024-11-16 12:55:19

听起来你必须做一些定制。
也许重写继承自的模型类的 parse 方法和 url 方法
骨干模型。

继承的函数是:

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
}

Sounds like you will have to do a little customization.
Perhaps override the parse method and url method of your model class inherited from
Backbone.Model.

The inherited functions are:

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;
},

and you could try something like:

parse: function(resp, xhr) {
    this._url = xhr.getResponseHeader('location')
    return resp
}
url: function() {
    return this._url
}
留一抹残留的笑 2024-11-16 12:55:19

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

正如您所指出的,进行第二次在线调用以完全实现模型没有什么意义。

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

Yes, backbone.js really wants the result of a save (be it PUT or POST) to be a parseable body which can be used to update the model. If, as you say, you have influence over the API, you should see if you can arrange for the content body to contain the resource attributes.

As you point out, its makes little sense to make a second over-the-wire call to fully materialize the model.

It may be that a status code of 200 is more appropriate. Purists may believe that a 201 status code implies only a location is returned and not the entity. Clearly, that doesn't make sense in this case.

心奴独伤 2024-11-16 12:55:19

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

这是我所做的一个示例,使其与 Backbone v0.9.9 和 jQuery 1.8.3 一起使用(使用 延迟对象/Promise),依赖于 Backbone 返回的jqXHR 对象。 Model.save()

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});
                }
            }
        });
    }
});

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

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

With Backbone 0.9.9, I couldn't get the accepted answer to work. The signature of the parse function seems to have changed in an older version, and the xhr object is no longer available in the function signature.

This is an example of what I did, to make it work with Backbone v0.9.9 and jQuery 1.8.3 (using a Deferred Object/Promise), relying on the jqXHR object returned by Backbone.Model.save() :

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});
                }
            }
        });
    }
});

I did not use the success callback that could be specified in the options hash provided to the Backbone.Model.save function, since that callback is invoked before the XHR response is received. That is, it is pointless to store a reference to the jqXHR object and use it in the success callback, since the jqXHR would not contain any response headers (yet) when the callback is invoked.

Another other to solve this would be to write a custom Backbone.sync implementation, but I didn't prefer this approach.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文