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
Backbone.js 嵌套主干模型在保存时会导致无限递归_Backbone.js - Fatal编程技术网

Backbone.js 嵌套主干模型在保存时会导致无限递归

Backbone.js 嵌套主干模型在保存时会导致无限递归,backbone.js,Backbone.js,这个问题似乎是在我更新到主干1.1时出现的。我有一个嵌套主干模型: var ProblemSet = Backbone.Model.extend({ defaults: { name: "", open_date: "", due_date: ""}, parse: function (response) { response.name = response.set_id; response.prob

这个问题似乎是在我更新到主干1.1时出现的。我有一个嵌套主干模型:

var ProblemSet = Backbone.Model.extend({
    defaults: {
        name: "",
        open_date: "",
        due_date: ""},
    parse: function (response) {
        response.name = response.set_id;
        response.problems = new ProblemList(response.problems);
        return response; 
    }
});

var ProblemList = Backbone.Collection.extend({
     model: Problem
});
我最初加载一个ProblemSetList,它是我页面中ProblemSet模型的集合。对任何问题集的open_date或due_date字段的任何更改,首先转到服务器并更新该属性,然后返回。这将对问题集触发另一个更改事件

似乎所有来自服务器的后续返回都会触发另一个更改事件,并且更改的属性就是“problems”属性。这将导致无限递归调用

这个问题似乎来自Backbone.Model的part-of-set方法(这里列出的代码来自第339行)

//对于每个“set”属性,更新或删除当前值。
for(属性中的属性){
val=attrs[attr];
如果(!u.isEqual(当前[attr],val])更改,则推送(attr);
如果(!u.isEqual(上一个[attr],val)){
this.changed[attr]=val;
}否则{
删除此项。已更改[attr];
}
取消设置?删除当前[attr]:当前[attr]=val;
}
//触发所有相关属性更改。
如果(!静默){
如果(更改.length)此值为.\u pending=true;
对于(变量i=0,l=changes.length;i
problems属性上的比较从u.isEqual()返回false,因此引发一个更改事件


我的问题是:这是嵌套主干模型的正确方法吗?我在主干网1.1中也有类似的工作。关于如何继续避免此问题的其他想法?

在获取和保存时调用parse(根据主干文档),这可能会导致无限循环。我不认为parse函数是创建新ProblemsList子集合的正确位置,而是在模型的initialize函数中执行它。

每次
模型.fetch
完成时,您都会重新实例化
问题
属性,对象不同,从而触发新的循环

我通常如何处理嵌套模型:

  • 在主干处理的属性之外使用模型属性
  • initialize
    函数中实例化它
  • set
    reset
    在父
    parse
    函数中设置此对象,并返回忽略设置数据的响应
大概是这样的:

var ProblemSet = Backbone.Model.extend({
    defaults: {
        name: "",
        open_date: "",
        due_date: ""
    },
    initialize: function (opts) {
        var pbs = (opts && opts.problems) ? opts.problems : [];
        this.problems = new ProblemList(pbs);
    },
    parse: function (response) {
        response.name = response.set_id;
        if (response.problems)
            this.problems.set(response.problems);
        return _.omit(response, 'problems');
    }
});

parse
中创建嵌套的主干模型/集合是一种既定的做法,感谢您的提示,以前没有看到过这一点;)我知道您已将
save
绑定到模型的
change
事件?是。类似于:problemSets.on(“change”,function(_set){_set.save();});我最新的想法是主干网1.1没有问题,但是要强调的是,它也更新到了1.5.2,并随之对带有对象的u.isEqual函数进行了一些更改。更多的探索使我得出以下结论:我上面引用的Backbone.js代码返回了一个changes变量,这意味着当前对象与刚从服务器发送的对象之间存在差异。原因似乎是新对象的ID与旧对象的ID不同;我之所以这样想,是因为他们执行了parse命令(上面列出),并创建了一个新的问题列表。一对新的问题可能是:对于这样的嵌套模型,我是否应该创建一个新的ProblemList集合(并保留旧ID),或者是否有其他方法?谢谢。如果您有机会,我的另一个一般性问题是如何存储嵌套模型。看起来您将其作为对象的字段(例如ProblemSet),而不是属性列表中的字段。您上面列出的方法是一种更可取的方法吗?@PeterStaab非常主观,但我更喜欢这种方法,因为正如您的问题所表明的那样,我不希望在重置/获取/炸属性(或在任何地方引入条件)时改变底层对象,我觉得它“更容易处理,更干净”。当然
var ProblemSet = Backbone.Model.extend({
    defaults: {
        name: "",
        open_date: "",
        due_date: ""
    },
    initialize: function (opts) {
        var pbs = (opts && opts.problems) ? opts.problems : [];
        this.problems = new ProblemList(pbs);
    },
    parse: function (response) {
        response.name = response.set_id;
        if (response.problems)
            this.problems.set(response.problems);
        return _.omit(response, 'problems');
    }
});