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});
мы использовали подход для замораживания пользовательского интерфейса, пока не будет выполнен запрос 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:{...}});