Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.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,我正在尝试在我的第一个“真实”应用程序中使用backbone.js,我需要一些帮助来调试为什么某些模型更改事件没有像我预期的那样触发 如果我从服务器的JSON数组中创建一个集合,然后以设置的间隔获取它,那么如果集合中的单个模型发生了更改,我不会得到通知。主干文档建议应生成此类通知。我似乎只在每次提取时收到一个刷新通知,这是没有用的。OTOH,如果我从服务器上的JSON对象创建一个模型,然后按设置的间隔获取()该模型,那么当属性更改时,我确实会收到更改通知。有什么想法吗 详细信息 我位于/empl

我正在尝试在我的第一个“真实”应用程序中使用backbone.js,我需要一些帮助来调试为什么某些模型更改事件没有像我预期的那样触发

如果我从服务器的JSON数组中创建一个集合,然后以设置的间隔获取它,那么如果集合中的单个模型发生了更改,我不会得到通知。主干文档建议应生成此类通知。我似乎只在每次提取时收到一个刷新通知,这是没有用的。OTOH,如果我从服务器上的JSON对象创建一个模型,然后按设置的间隔获取()该模型,那么当属性更改时,我确实会收到更改通知。有什么想法吗

详细信息

我位于/employees/{username}/tasks的web服务返回任务对象的JSON数组,每个任务对象嵌套子任务对象的JSON数组。比如说,

[{
  "id":45002,
  "name":"Open Dining Room",
  "subtasks":[
    {"id":1,"status":"YELLOW","name":"Clean all tables"},
    {"id":2,"status":"RED","name":"Clean main floor"},
    {"id":3,"status":"RED","name":"Stock condiments"},
    {"id":4,"status":"YELLOW","name":"Check / replenish trays"}
  ]
},{
  "id":47003,
  "name":"Open Registers",
  "subtasks":[
    {"id":1,"status":"YELLOW","name":"Turn on all terminals"},
    {"id":2,"status":"YELLOW","name":"Balance out cash trays"},
    {"id":3,"status":"YELLOW","name":"Check in promo codes"},
    {"id":4,"status":"YELLOW","name":"Check register promo placards"}
  ]
}]
另一个web服务允许我更改特定任务中特定子任务的状态,如下所示:/tasks/45002/subtask/1/status/red[旁白-我打算将其更改为基于HTTP Post的服务,但当前的实现更易于调试]

我的JS应用程序中有以下类:

子任务模型和子任务集合

var Subtask = Backbone.Model.extend({});

var SubtaskCollection = Backbone.Collection.extend({
  model: Subtask
});
var Task = Backbone.Model.extend({
  initialize: function() {

    // each Task has a reference to a collection of Subtasks
    this.subtasks = new SubtaskCollection(this.get("subtasks"));

    // status of each Task is based on the status of its Subtasks
    this.update_status();

  },
  ...
});

var TaskCollection = Backbone.Collection.extend({
  model: Task 
});
具有子任务集合嵌套实例的任务模型

var Subtask = Backbone.Model.extend({});

var SubtaskCollection = Backbone.Collection.extend({
  model: Subtask
});
var Task = Backbone.Model.extend({
  initialize: function() {

    // each Task has a reference to a collection of Subtasks
    this.subtasks = new SubtaskCollection(this.get("subtasks"));

    // status of each Task is based on the status of its Subtasks
    this.update_status();

  },
  ...
});

var TaskCollection = Backbone.Collection.extend({
  model: Task 
});
任务视图以呈现项目并侦听模型的更改事件

var TaskView = Backbone.View.extend({

  tagName:  "li",

  template: $("#TaskTemplate").template(),

  initialize: function() {
    _.bindAll(this, "on_change", "render");
    this.model.bind("change", this.on_change);
  },

  ...

  on_change: function(e) {
    alert("task model changed!");
  }

});
当应用程序启动时,我实例化一个TaskCollection(使用上面列出的第一个web服务中的数据),将更改事件的侦听器绑定到TaskCollection,并设置一个循环setTimeout()来获取TaskCollection实例

...

TASKS = new TaskCollection();

TASKS.url = ".../employees/" + username + "/tasks"

TASKS.fetch({
  success: function() {
    APP.renderViews();
  }
});


TASKS.bind("change", function() {
  alert("collection changed!");
  APP.renderViews();
});


// Poll every 5 seconds to keep the models up-to-date.
setInterval(function() {
  TASKS.fetch();  
}, 5000);

...
第一次渲染时,一切都按预期进行。但此时,如果我使用第二个web服务更改子任务的状态,我希望触发集合更改事件或模型更改事件中的一个(或两个),但这不会发生

有趣的是,如果我添加了一个额外的嵌套级别,web服务返回一个模型,我确实会触发更改事件,例如:

"employee":"pkaushik", "tasks":[{"id":45002,"subtasks":[{"id":1.....
但这似乎是克鲁吉。。。恐怕我还没有正确设计我的应用程序。如果有帮助的话,我将包含更多的代码,但这个问题已经相当冗长了


想法?

您正在收听任务中的事件,而不是您的子任务。如果希望任务也包含子任务的事件,则应在任务中执行类似操作。初始化:

var self = this;    
this.subtasks.bind("refresh", function(){ self.trigger("refresh:subtask")});
this.subtasks.each(function(st){ 
  st.bind("change", function(){ self.trigger("change:subtask:" + st.id, st) });
});
您可能还希望在刷新事件之后刷新绑定。这样,当子任务模型上发生更改事件时,任务模型也将触发更改模型

主干网将仅在获取后发送刷新事件,而不会通知您特定模型中的更改。查看collection的fetch函数:

options.success = function(resp) {
  collection[options.add ? 'add' : 'refresh'](collection.parse(resp), options);
  if (success) success(collection, resp);
};
默认情况下,它将调用刷新。以下是刷新功能:

refresh : function(models, options) {
  models  || (models = []);
  options || (options = {});
  this.each(this._removeReference);
  this._reset();
  this.add(models, {silent: true});
  if (!options.silent) this.trigger('refresh', this, options);
  return this;
}

它将以静默方式(无事件)将所有模型添加到集合中,然后触发刷新事件,但不会识别已更改的元素。

感谢您的回复!我按照您的建议向集合中的每个模型添加了更改事件处理程序,但不幸的是,这没有帮助。我编辑了原始帖子,以便更好地描述我面临的问题(见第二段)。至于您关于监听子任务中的更改的评论,我不认为从事件的角度来看这有什么关系——“子任务”是任务模型的一个属性,我只是碰巧将其转换为一个嵌套集合。我的问题似乎比我最初想象的要简单-我只是没有收到集合中模型的更改通知。好东西,Julien-非常喜欢你对SORight上与主干相关的东西的响应-Backbone.js只会触发模型上的更改事件,并在集合上添加/删除/刷新事件;但我需要知道集合中是否有任何单个模型发生了更改,因为我正在轮询集合URL,并且不希望每次轮询时都在内存中重建集合。如前所述,我最初的(hacky)解决方案是将相同的数据加载到模型和集合中,并且只有在收到模型更改事件时才重新加载集合。我现在已经完全不再使用轮询,而是使用Comet将服务器上的更改通知客户机——到目前为止,这一切都非常有效。