【问题标题】:waiting till an on change handler is complete before saving model在保存模型之前等待更改处理程序完成
【发布时间】:2013-01-06 11:16:24
【问题描述】:

我有一个用户模型(Backbone.js),我想更新其设置属性,然后将其保存到服务器。设置是 JSON 格式,我设置它的方式是设置是字符串版本,settingsJSON 是对象版本。我将函数绑定到每个函数的更改事件,以便当一个函数更改时,它会更新另一个函数。

我遇到的问题是 save 方法在更改的处理程序完成运行之前运行。有什么办法可以确保该模型的所有事件处理程序都是完整的或类似的东西?

我怎么称呼它:

currentUser.get('settingsJSON').apps = appsEnabled;
currentUser.save();

我的事件处理程序:

Initialize: function() {
    var that = this;
    this.on("change:settingsJSON", function(model){
        model.set({settings: JSON.stringify(model.get('settingsJSON'))});
    });

    this.on("change:settings", function(model){
        model.set({settingsJSON: JSON.parse(model.get('settings'))});
    });
}

@fencliff:

当我运行它并正常工作时,更改事件正在触发,我让它将新的设置字符串打印到控制台。

您确定它们是同步调用的吗?我将console.log('changed') 添加到.on(change) 的末尾,并将console.log('saved') 直接放在currentUser.save() 之后,每次控制台读取:

saved
changed

现在我刚刚制作了它,以便在保存之前将 JSON 字符串化并直接保存到设置中,效果很好。

【问题讨论】:

  • 相对确定事件是同步触发的,而且model.get('settingsJSON').apps = true不会触发任何事件。但是我已经在这个线程中错了两次,所以我知道什么。这是一个演示:jsfiddle.net/T7jKg。你能分叉它并显示你的代码中发生了什么吗?
  • @fencliff 我认为一定是发生了改变被其他东西触发了,可能是 .save()。不完全确定。稍后我可能会重新访问它以尝试让它按我想要的方式工作,但现在我的修复将起作用

标签: javascript events backbone.js


【解决方案1】:

Backbone 事件是同步执行的。这意味着除非您(或某个库)覆盖了事件处理的某些部分,否则一旦您执行下一行代码,更改处理程序就会被处理。

在您的代码示例中还有另一个问题。当你打电话时

user.get('settingsJSON').apps = appsEnabled;

change 事件将不会触发,因为 settingsJSON 的值没有改变,只是对象的内容被修改了。 model.attributes.settingsJSON 仍然是以前的对象。

仅当您在属性上调用set 并且新值是一个不同 对象时才会触发这些事件。例如:

user.set('settingsJSON', _.extend({}, user.get('settingsJSON'), {apps:appsEnabled});

另一个问题似乎是,如果您的事件处理程序被触发,将导致 change 事件针对第一次设置的属性被触发两次:

this.on("change:settingsJSON", function(model){
    //-> changes settings, and set triggers change
    model.set({settings: JSON.stringify(model.get('settingsJSON'))});
});

this.on("change:settings", function(model){
    //-> changes settingsJSON, and set triggers change
    model.set({settingsJSON: JSON.parse(model.get('settings'))});
});

要解决该问题,请使用{silent:true} 调用set 或直接修改model.attributes 哈希。

已编辑,@muistooshort 进行了更正。

编辑再次进行了更正

【讨论】:

  • 你确定这两个set 调用会触发"change" 事件吗?
  • @muistooshort,我不明白他们为什么不这样做,但是我又喝醉了,在手机上所以无法测试。他们为什么不呢?
  • 它们不会因为set 本质上使用== 来跳过设置未更改的属性,向对象添加新属性不会更改其引用值。你需要提交set 类似_.extend({}, user.get('settingsJSON'), { apps: appsEnabled }) 的东西来强制生成一个新对象,这样你就可以通过简单的平等过滤器。
  • 更多关于这个特定set陷阱的详细信息:stackoverflow.com/a/13369672/479863stackoverflow.com/a/11662381/479863
  • @fencliff 查看我的编辑。不过,我确实将它们更改为 {silent: true},请注意。 mu太短了,我看看那些
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多