Подтвердить что ты не робот

Какой лучший способ обработать REST API "создать" ответ в Backbone.js

Я использую backbone.js для взаимодействия с REST API, который при отправке на него для создания нового ресурса отвечает статусом 201, заголовком "Местоположение", указывающим на URI ресурса, но пустым телом.

Когда я создаю новую модель на данный момент, ее успешное, но локальное представление модели содержит только те свойства, которые я явно задал, а не любые свойства, которые будут установлены на сервере (created_date и т.д.)

Из того, что я понимаю, Backbone будет обновлять свое представление модели данными в теле, если таковые имеются. Но, поскольку нет, это не так.

Итак, очевидно, мне нужно использовать расположение в заголовке Location для обновления модели, но лучший способ сделать это.

Мое текущее мышление заключается в том, что мне нужно будет разобрать URL-адрес из заголовка, разделить идентификатор, установить идентификатор для модели, а затем сообщить модели для извлечения().

Это кажется действительно грязным. Есть ли более чистый способ сделать это?

У меня есть некоторое влияние на API. Лучшее решение, чтобы попытаться заставить автора API вернуть новую модель в качестве тела ответа (сохраняя также 201 и заголовок местоположения)?

Спасибо!

4b9b3361

Ответ 1

Похоже, вам придется немного настроить. Возможно, переопределить метод parse и метод 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
}

Ответ 2

Да, backbone.js действительно хочет, чтобы результат сохранения (будь то PUT или POST) был анализируемым телом, который можно использовать для обновления модели. Если, как вы говорите, вы имеете влияние на API, вы должны увидеть, можете ли вы организовать, чтобы тело содержимого содержало атрибуты ресурса.

Как вы отмечаете, мало смысла сделать второй сквозной звонок для полной материализации модели.

Возможно, код статуса 200 более подходит. Пуристы могут полагать, что код состояния 201 означает, что возвращается только местоположение, а не объект. Ясно, что в этом случае это не имеет смысла.

Ответ 3

С Backbone 0.9.9 я не мог получить принятый ответ на работу. Подпись функции parse, по-видимому, изменилась в более старой версии, а объект xhr больше не доступен в сигнатуре функции.

Это пример того, что я сделал, чтобы он работал с Backbone v0.9.9 и jQuery 1.8.3 (используя Отложенный объект/обещание), полагаясь на jqXHR объект, возвращенный 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});
                }
            }
        });
    }
});

Я не использовал обратный вызов success, который может быть указан в хеше options, предоставленном функции Backbone.Model.save, так как этот обратный вызов вызывается до получения ответа XHR. То есть бессмысленно хранить ссылку на объект jqXHR и использовать его в обратном вызове success, так как jqXHR не будет содержать заголовки ответов (пока) при вызове обратного вызова.

Другим решением этой проблемы было бы написать пользовательскую реализацию Backbone.sync, но я не предпочел этот подход.