Backbone сохранить без набора на обратный вызов

У меня есть функция перетаскивания в моем веб-приложении. Когда пользователь отпускает мышь после перетаскивания, положение объекта сохраняется на сервере с помощью метода Save() магистрали на модели. Когда сервер отвечает, он запускает set() в модели с возвращаемыми свойствами. Однако во время обработки запроса сервером пользователь, возможно, уже снова перетащил объект в другое положение. Это вызывает проблемы, поскольку ответ от сервера теперь будет переопределите настройки объекта в браузере.

есть ли способ предотвратить выполнение Backbone set () после того, как он получит ответ от сервера после save ()?

10 ответов


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

вы можете переопределить модель parse ()


посмотрите на опцию "ждать", по умолчанию она должна быть установлена в false, что означает, что ваши поля модели должны быть установлены сразу после вызова save(). Можно задать {wait: true}, чтобы заставить магистраль ждать ответа сервера перед установкой обновленных значений полей модели.

из вашего описанного поведения похоже, что параметр wait установлен в true в вашем приложении.

дополнительные сведения:http://backbonejs.org/#Model-save

еще один важный следует помнить, что backbone устанавливает только подмножество обновленных полей, которые вы возвращаете из вызываемого webservice, поэтому, если вы не возвращаете их, никто не будет установлен.


Model.save будем называть Model.parse по данным, полученным с теми же options аргумент, прежде чем устанавливать его.

можно назвать Model.save с пользовательским флагом (скажем position: true), указывая, что Model.parse может отбросить то, что сервер возвращает.

например, если ваши координаты x и y

var M = Backbone.Model.extend({
    parse: function(data, options)  {
        if (options && options.position)
            data = _.omit(data, 'x', 'y');

        return data;
    }
});

var m = new M();
m.save({x: 10, y:10}, {position: true});
m.save({x: 20, y:20}, {position: true});

и демо http://jsfiddle.net/nikoshr/YwC7q/


мы использовали подход для замораживания пользовательского интерфейса, пока не будет выполнен запрос ajax. Мы добавили два дополнительных события freeze / unfreeze к модели, которая срабатывала до сохранения и после получения ответа от разъединителя.


попробовать переопределить '.метод sync (). Позвоночник.делегаты save () в магистраль.sync () после переопределения успешного обратного вызова, который вы передаете. Вот откуда идет обновление модели.

от источника позвоночника.метод save ():

var success = options.success;
  options.success = function(resp) {
    // Ensure attributes are restored during synchronous saves.
    model.attributes = attributes;
    var serverAttrs = model.parse(resp, options);
    if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
    if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
      return false;
    }
    if (success) success(model, resp, options);
    model.trigger('sync', model, resp, options);
  };
  wrapError(this, options);

  method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
  if (method === 'patch') options.attrs = attrs;
  xhr = this.sync(method, this, options);

вы можете передать пользовательский параметр при вызове '.save ()', затем найдите эту опцию и переопределите параметры.успех обратного вызова '.синхронизация.')( Что-то вроде этого?

MyModel = Backbone.Model.extend({
    sync: function (method, context, options) {
        if (options.skipUpdateOnResponse) {
            options.success = myCusomSuccessFunction;
        }
    }
});

myModel = new MyModel();

myModel.save({...}, {skipUpdateOnResponse: true})

свойства сервера отвечает? Обратный вызов успеха по умолчанию, который использует Backbone, делает это:

if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { ... }

следуя этой логике, если ваш сервер не возвращает объект, set Не следует вызывать на вашей модели.

кроме того, если вы измените свой ответ сервера, чтобы он не возвращал информацию о позиции ,которая передается (что является основной причиной вашей проблемы и без понимания ваших требований, также кажется немного избыточным) эти свойства не должны переопределяться, когда set называется.

запрет этих параметров, переопределение sync как предлагает @Uselessinfo или вводит некоторые хитрости в parse вероятно, ваши следующие лучшие ставки.


используйте метод validate для модели:

validate: function(attrs) {
    var errors = [];
    if (attrs.position !== this.get('position')) {
        errors.push('Outdated info!');
    }
    return _.any(errors) ? errors : null;
}

таким образом, вы можете сравнить ответ сервера с существующими данными в модели. Если ответ сервера отличается от данных в модели, верните ошибки и set метод не будет вызван. Это может потребовать wait: true на save параметры метода. При таком подходе, я думаю, вы должны установить позицию на модели, прежде чем делать фактическое сохранение.

проверка вызывается перед сохранением, но также можно вызвать перед set if {validate: true}


Backbone сохранить успех обратного вызова:

  options.success = function(resp, status, xhr) {
    done = true;
    var serverAttrs = model.parse(resp, xhr);
    if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
    if (!model.set(serverAttrs, options)) return false;
    if (success) success(model, resp, options);
    model.trigger('sync', model, resp, options);
  };

поэтому он вызывает set allways перед вызовом триггера "sync" и перед вызовом функции успеха пользователя. Нет никакого способа предотвратить позвоночник делать набор, но есть способ решить вашу проблему. Вы можете переопределить функцию " set " в своей модели следующим образом:

set: function() {
  if (this.skipSetOperation()) return false;
  return Backbone.Model.prototype.set.apply(this, arguments);
},

skipSetOperation: function() {
  //this function should return stage - can model set attributes in this moment or not
}

надеюсь, что это помогает.


сейчас я использую следующее решение:

переопределить метод синтаксического анализа модели по умолчанию:

Backbone.Model.prototype.parse = function(resp, options) {
    if(options.parse)
        return resp;
};

теперь вы можете использовать метод save со свойством "parse", установленным в false, чтобы предотвратить ответ ajax для переопределения ваших текущих значений:

MyModel.save({}, { parse: false });

напишите другую функцию для сохранения, и вместо использования save используйте свою функцию.

модель:

var myModel = Backbone.Model.extend({
     savePosition: function(){
           var model = this;    
           $.ajax({
                type : "POST",
                cache: false,
                dataType : 'json',
                contentType : 'application/json',
                data:JSON.stringify(data),
                url : "urlToSave",
                success:function(responseText,statusText){
                    model.trigger('saved',responseText);
                },
                error : function(error, dataObj, xhr) {
                                        alert('Error');
                }
      });    
     }
}

здесь в поле зрения bind метод сохранен, и вызвать метод после сохранения.

this.model.on('saved',function(){
   // do call back stuff
});
this.model.savePosition({data:{...}});