Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在回调时不设置主干存储_Javascript_Backbone.js - Fatal编程技术网

Javascript 在回调时不设置主干存储

Javascript 在回调时不设置主干存储,javascript,backbone.js,Javascript,Backbone.js,我的web应用程序中有拖放功能。当用户在拖放后释放鼠标时,对象的位置将使用模型上主干的save()方法保存到服务器。当服务器响应时,它会使用返回的属性在模型上触发set()。但是,在服务器处理请求时,用户可能已经再次将对象拖动到其他位置。这会导致问题,因为服务器的响应现在将覆盖浏览器中对象的设置 是否有办法防止主干在save()之后从服务器获得响应后执行set()?查看“wait”选项,默认情况下,它应设置为false,这意味着在调用save()后应立即设置模型字段。您可以设置{wait:tru

我的web应用程序中有拖放功能。当用户在拖放后释放鼠标时,对象的位置将使用模型上主干的save()方法保存到服务器。当服务器响应时,它会使用返回的属性在模型上触发set()。但是,在服务器处理请求时,用户可能已经再次将对象拖动到其他位置。这会导致问题,因为服务器的响应现在将覆盖浏览器中对象的设置

是否有办法防止主干在save()之后从服务器获得响应后执行set()?

查看“wait”选项,默认情况下,它应设置为false,这意味着在调用save()后应立即设置模型字段。您可以设置{wait:true}使主干网在设置更新的模型字段值之前等待服务器回复

从您描述的行为来看,应用程序中的wait选项似乎设置为true

进一步详情:


另一件需要记住的重要事情是主干网只设置您从被调用的Web服务返回的更新字段的子集,因此,如果您不返回任何字段,则将不设置任何字段。

以前在执行系统时有类似的用例,尽管这更麻烦,因此我们需要真正覆盖模型
set()
函数。尽管对于这种情况,有两种相对简单的方法可用

可以替代模型函数。或者,您可以对
save()
调用返回的jqXHR对象调用
abort()


为保存编写另一个函数,使用该函数代替保存

在模型中:

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');
                }
      });    
     }
}
这里查看保存的绑定方法,并在保存后触发该方法

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

我们使用这种方法来冻结UI,直到执行ajax请求为止。我们在模型中添加了两个额外的事件冻结/解冻,分别在保存之前和从服务器收到应答之后触发。

尝试覆盖“.sync()”方法。在覆盖传入的成功回调后,Backbone.save()将委托给Backbone.sync()。这就是模型更新的来源

从主干.save()方法的源:

您可以在调用“.save()”时传递一个自定义选项,然后在“.sync()”中查找该选项并重写options.success回调。也许是这样的

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

myModel = new MyModel();

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

服务器响应的属性是什么?主干网使用的默认成功回调执行以下操作:

if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { ... }
按照此逻辑,如果服务器不返回对象,则不应在模型上调用
set

或者,如果修改服务器响应,使其不返回传入的位置信息(这是问题的根本原因,并且在不了解您的要求的情况下,也似乎有点多余),则在调用
set
时,不应覆盖这些属性


如果不使用这些选项,则按照@Uselessinfo的建议覆盖
sync
,或者在
parse
中使用一些技巧可能是您的下一个最佳选择。

在模型上使用验证方法:

validate: function(attrs) {
    var errors = [];
    if (attrs.position !== this.get('position')) {
        errors.push('Outdated info!');
    }
    return _.any(errors) ? errors : null;
}
通过这种方式,您可以将服务器响应与模型中的现有数据进行比较。如果服务器响应与模型中的数据不同,则返回错误,并且不会调用
set
方法。这可能需要
save
方法选项中的
wait:true
。使用这种方法,我认为您应该在执行实际保存之前在模型上设置位置

validate在保存之前调用,但如果{validate:true},也可以在set之前调用


主干存储成功回调:

  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);
  };
因此,它在调用触发器“sync”和用户成功函数之前调用set allways。 并没有办法阻止你们们去做这件事,但有办法解决你们们的问题。 您可以通过以下方式覆盖模型中的“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
}

希望有帮助。

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

还有一个演示

我现在使用以下解决方案:

覆盖模型的默认分析方法:

Backbone.Model.prototype.parse = function(resp, options) {
    if(options.parse)
        return resp;
};
现在,您可以使用属性“parse”设置为false的save方法来防止ajax响应覆盖当前值:

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

谢谢你的建议,但是我没有将等待选项设置为true。问题是,如果返回的参数与当前模型上的参数不同,主干在服务器响应后将始终使用set方法。但这会影响所有保存操作,对吗?因为我不想破坏其他保存操作的功能。除非您覆盖
model.save
,否则在成功回调时调用
abort
为时已晚,主干网自己的回调将被执行,因此您的模型已经设置了服务器属性。关于最初的问题…不幸的是没有,没有这样的选择。但是,最简单的方法是编写自己的服务器同步功能,并使用该功能而不是
model.save
。您也可以仅为该特定模型覆盖
save
。更具体的解决方案可能包括在
模型内创建某种更新时间戳或版本计数器。验证
模型。解析
您可以使用时间戳或计数器进行操作。您可以覆盖
解析()
仅在特定型号上运行。我同意,在成功回拨时调用
中止将为时已晚。我的意思是对圣
MyModel.save({}, { parse: false });