如何更改对象时如何通知观察者?

时间:2012-02-22 23:48:04

标签: javascript ember.js

简短版:有没有办法确保观察者得到变更的通知,无论如何,即使Ember不认为某个属性发生了变化?

一般来说,余烬观察者模式对我有用,但在这里我被卡住了。我不确定这是一个错误或诸如此类的东西,还是一个特征,但是这件事让我感到困扰。

在这个场合,我会很高兴某种形式的myinstance.fireNotificationsNoMatterWhat("cache"),但我在代码中找不到类似的东西。有什么我想念的吗?

下面的示例代码显示了问题。

<!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>

编辑:看起来这个问题有短期修复,但是在尝试了我自己的“修复”之后,并尝试了下面的Roy的建议,我认为我的核心问题将无法回答直到这个enhancement request从繁忙的余烬团队那里得到一些爱。如果它最终给了我ArrayProxy给我的东西,我可以等待它。

1 个答案:

答案 0 :(得分:1)

好的,发现了问题,不,这不是一个错误。发生的事情是Test.cacheObject.cache设置的哈希不会改变。基本上你没有将实际的哈希值改为另一个哈希值...你只是在内存中改变相同哈希值的属性。

请查看this jsFiddle以获得解决方案,但只需缩短版本,您只需将var cache = this.get("cache");更改为var cache = {};

修改

由于必须保持数据的唯一性,我能想到的另一件事就是让缓存成为一个数组,并在观察cache.@each时只分配键/值对。我已经更新了jsFiddle以显示这一点。希望这种解决方法能够满足您的目标。

<强> EDIT2:

立即查看jsFiddle。睡了一会后我想到了一个满足你所有要求的解决方案。哦,我不相信“没有解决方案”......每个问题都有解决方案!