Javascript 当对象发生变化时,如何通知观察者?
简短版本:是否有办法确保观察者在任何情况下都能收到更改通知,即使Ember认为某个属性没有更改? 一般来说,余烬观察者模式适合我,但在这里我被卡住了。我不确定这是一个bug还是什么,或者是一个功能,但是这方面的一些事情让我很困扰 在这种情况下,我很乐意使用某种形式的Javascript 当对象发生变化时,如何通知观察者?,javascript,ember.js,Javascript,Ember.js,简短版本:是否有办法确保观察者在任何情况下都能收到更改通知,即使Ember认为某个属性没有更改? 一般来说,余烬观察者模式适合我,但在这里我被卡住了。我不确定这是一个bug还是什么,或者是一个功能,但是这方面的一些事情让我很困扰 在这种情况下,我很乐意使用某种形式的myinstance.firennotifications无论什么(“缓存”),但我在代码中找不到类似的东西。有什么我遗漏的吗 下面显示问题的示例代码 <!DOCTYPE html> <html> &l
myinstance.firennotifications无论什么(“缓存”)
,但我在代码中找不到类似的东西。有什么我遗漏的吗
下面显示问题的示例代码
<!DOCTYPE html>
<html>
<head>
<title>emberjs notification test</title>
<!-- using current (at the time) version 0.9.5, from emberjs.com
starter kit. -->
<script src="jquery-1.6.1.min.js"></script>
<script src="ember-0.9.5.min.js"></script>
<script>
Test = Ember.Application.create({});
// I don't want an arrayproxy this time, and would be happy to find
// out if there is some form of ObjectProxy?
Test.cacheObject = Ember.Object.create({
"cache": {},
"add": function(key, value) {
// In other situations, I don't need
// propertyWillChange/propertyDidChange, but here
// I'm stuck, and I can't notify listeners when my
// cache changes, so I figured I'd try out
// these commands, which don't work, either.
this.propertyWillChange("cache");
var cache = this.get("cache");
cache[key] = value;
this.set("cache", cache);
this.propertyDidChange("cache");
},
});
// Contrived watcher.
Test.watcher = Ember.Object.create({
// One of the many ways I've tried to bind to the
// the object to get the observer to fire.
"cacheBinding": "Test.cacheObject.cache",
"obs": function() {
// Ideally, whenever I call Test.cacheObject.add in different call
// stacks I should be notified.
console.log("cache has changed:");
console.log(this.get("cache"));
}.observes("cache"),
});
setTimeout(function() {
// I get notified on the first add...
Test.cacheObject.add("hello", "world");
}, 500);
setTimeout(function() {
// ...but I will not get notified on the second, or any subsequent addition.
Test.cacheObject.add("and", "universe");
}, 1000);
</script>
</head>
<body>
<h1>emberjs notification test</h1>
<h2>Please open your console to see the console.log output.</h2>
</body>
</html>
通知测试
Test=Ember.Application.create({});
//这次我不想要arrayproxy,我很乐意找到
//是否存在某种形式的ObjectProxy?
Test.cacheObject=Ember.Object.create({
“缓存”:{},
“添加”:功能(键、值){
//在其他情况下,我不需要
//propertyWillChange/PropertyIDChange,但在这里
//我被困住了,我不能通知听众我的
//缓存更改,所以我想我应该试试
//这些命令也不起作用。
此。propertyWillChange(“缓存”);
var cache=this.get(“cache”);
缓存[键]=值;
这个.set(“cache”,cache);
此.propertyDidChange(“缓存”);
},
});
//人为的观察者。
Test.watcher=Ember.Object.create({
//我尝试过的许多方法中的一种
//使观察者开火的对象。
“cacheBinding”:“Test.cacheObject.cache”,
“obs”:函数(){
//理想情况下,每当我调用Test.cacheObject.add时,都会调用不同的调用
//我应该得到通知。
log(“缓存已更改:”);
log(this.get(“缓存”);
}.观察到(“缓存”),
});
setTimeout(函数(){
//我在第一次添加时收到通知。。。
Test.cacheObject.add(“hello”,“world”);
}, 500);
setTimeout(函数(){
//…但我不会得到第二次或任何后续添加的通知。
Test.cacheObject.add(“and”,“universe”);
}, 1000);
通知测试
请打开控制台以查看console.log输出。
编辑:看起来这个问题有短期的解决方案,但是在尝试了我自己的“解决方案”和下面罗伊的建议之后,我认为我的核心问题将无法回答,直到这得到忙碌的余烬团队的一些爱。如果ArrayProxy最终给了我ArrayProxy给我的东西,我可以等待。好的,我发现了问题,不,这不是一个bug。发生的是
Test.cacheObject.cache
设置为的哈希值没有改变。基本上,您并没有将实际哈希更改为另一个哈希。。。您只是在内存中更改同一哈希上的属性
查看一个解决方案,但简短的版本,您只需要更改var cache=this.get(“cache”)代码>到var cache={}代码>
编辑:
由于必须保留数据,我唯一能想到的另一件事是让缓存成为数组,并在观察缓存时为其分配键/值对。@each
。我已经更新了JSFIDLE来显示这一点。希望这个变通方法能为您所要完成的工作起作用
edit2:
现在查看JSFIDLE。睡了一会儿后,我想到了一个满足您所有要求的解决方案。哦,我不相信“没有解决方案”。。。每个问题都有解决办法 如果你注意到在这个例子中,我正在这样做。如果你运行代码,它就不工作了,或者更确切地说,它只工作一次。我很高兴发现我的代码是错误的,现在有一个解决方案,但我认为,鉴于我在github for ember上看到的情况,我可能不得不等待ObjectProxy。嗨,ud3323,我应该澄清一下,你是对的,上面的代码没有显式地尝试静态Ember.propertyWillChange
和Ember.propertyDidChange
,而是使用实例方法。然而,不幸的是,我尝试了静态版本,它们也不起作用。悲伤的脸。抱歉,只看简短的版本。没有看到运行代码的JSFIDLE,但我会为您制作一个。请给我几分钟时间检查您的代码。您好ud3323。感谢您的回答,但是您的回答实际上是转储任何预先存在的数据,这不是答案。我需要的缓存可能有数百个,甚至在某些点上有数千个,被引用的小对象。每次我只想添加一个新的key:value或用一个新值更新一个现有的key时,将所有引用的对象从object复制到新的object实例是不可接受的。我所希望的是某种形式的myObject.notifyPropertyIDChange
,它可以强制激发所有侦听的观察者,不管底层值是否已更改。让我们