1

我正在为围绕有状态对象和可观察存储的 MVC 模式而苦苦挣扎。我无法明确何时使用一个而不是另一个,并且混合它们并不像我希望的那样干净。随便啊!深入了解如何管理可观察的有状态项集合?

如果我做一个 item.set("key", value) 我可以 item.watch("key", cb) 但是我的观察者没有被通知。

我可以做一个 item.watch(function() { state.notify(item, item.id); }) 来总是通知我的观察者但是如果我的观察者调用集我得到一个“查询已过期,你必须在任何数据修改之前观察()查询”错误我无法协调。

我可以通过 setTimeout 解耦,但感觉不太好。

这是一些代码来显示我正在尝试的内容:

    crudify: function ( store, query, crud )
    {
        var result;
        if ( !crud )
        {
            crud = query;
            query = store;
            store = null;
        }
        if ( store )
        {
            query = store.query( query );
        }
        result = query.observe( function ( row, deleteIndex, insertIndex )
        {
            var del = ( 0 <= deleteIndex ), ins = ( 0 <= insertIndex );
            !del && ins && crud.c && crud.c( row );
            del && ins && crud.u && crud.u( row );
            del && !ins && crud.d && crud.d( row );
        }, !!crud.u );
        crud.c && array.forEach( query, crud.c );
        return result;
    }

而且我有一个存储包装器(用于图层),我将其分解成碎片,试图让观察者通知数据更改而不会出错:

addLayer: function ( item ) {
    var that = this;
    that.store.add(item);
    item.watch && item.watch(function (name, prior, curr) {
        if (prior !== curr) {
            that._queue.push(item);
            // attempting to eliminate queries which indirectly update the store (can't find source of error)
            infor.delay(20, "LayerProcessorStoreNotification", function () {
                that._queue.forEach(function (item) {
                    that.store.notify(item, that.getLayerId(item));
                });
                that._queue = [];
            });
        }
    });
    return item;
},

延迟方法如下所示:

    delay: function ( timeout, id, callback )
    {
        this.delays = this.delays || [];
        var delay = this.delays[id];
        if ( delay )
        {
            clearTimeout( delay );
        }
        delay = setTimeout( callback, timeout );
        this.delays[id] = delay;
    },
4

1 回答 1

1

我可以做一个 item.watch(function() { state.notify(item, item.id); }) 总是通知我的观察者

我使用这种模式没有任何问题,但是......

但是如果我的观察者调用设置我得到一个“查询已过时,您必须在任何数据修改之前观察()查询”错误我无法协调。

你不应该有watchcallnotify也有observecall set。选择一个或另一个。否则,您将自己设置为无限循环的回调。

下面的代码对我有用。我对您的crudify功能所做的唯一更改是更改array.forEach(query, crud.c)query.forEach(crud.c).

<script type="text/javascript" src="../javascripts/dojo-release-1.9.3-src/dojo/dojo.js"></script>
<script type="text/javascript">

window.stackoverflow = {
    crudify: function ( store, query, crud )
    {
        var result;
        if ( !crud )
        {
            crud = query;
            query = store;
            store = null;
        }
        if ( store )
        {
            query = store.query( query );
        }
        result = query.observe( function ( row, deleteIndex, insertIndex )
        {
            console.log("Observed");
            var del = ( 0 <= deleteIndex ), ins = ( 0 <= insertIndex );
            !del && ins && crud.c && crud.c( row );
            del && ins && crud.u && crud.u( row );
            del && !ins && crud.d && crud.d( row );
        }, !!crud.u );
        crud.c && query.forEach( crud.c );
        return result;
    }
};

require([
    "dojo/store/Memory",
    "dojo/store/Observable",
    "dojo/Stateful",
    "dojo/_base/json",
    "dojo/domReady!"
], function(Memory, Observable, Stateful, dojo){

    var store = Observable(new Memory({ data: [] })); 
    var rawData = [ { id: 1, data: "A" }, { id: 2, data: "B" }, { id: 3, data: "C" }]

    var myQuery = { id : 3 };

    rawData.forEach(function (obj, index) {
      statefulObj = new Stateful(obj);
      statefulObj.watch(function(name, oldValue, newValue) {
        console.log("Watched");
        store.notify(statefulObj, statefulObj.id);
      });                                                            
      store.put(statefulObj);
    });

    window.setTimeout(function() { 
        // this directly triggers the observe() callback
        store.notify(store.get(3), 3);
    }, 2000);

    window.setTimeout(function() { 
        // this triggers the watch(), which indirectly triggers observe() through notify()
        store.get(3).set("data", "Sea?");
    }, 4000);

    window.setTimeout(function() {                                                     
        // this calls no callbacks because it doesn't match the query                                                             
        store.put({ id: 2, data: "Bee" });
    }, 6000);

    window.setTimeout(function() { 
        // this update triggers observe()
        store.put(new Stateful({ id: 3, data: "See!?!" }));

        // note that we didn't set up a watch() on this new object (see below)
    }, 8000);

    window.setTimeout(function() { 
        // whoops, this doesn't trigger a callback because we forgot to call watch() above
        store.get(3).set("data", "C4");
    }, 10000);

    window.setTimeout(function() { 
        // but the observe() callback still works
        store.notify(store.get(3), 3);
    }, 12000);

    window.setTimeout(function() { 
        // this deletion triggers observe()
        store.remove(3);
    }, 14000);

    stackoverflow.crudify(
        store,
        myQuery,
        {
          u: function(obj) {
            console.log("Observed update: obj: " + dojo.toJson(obj));
          },
          c: function(obj) {
            console.log("Observed creation: obj: " + dojo.toJson(obj));
          },
          d: function(obj) {
            console.log("Observed deletion: obj: " + dojo.toJson(obj));
          }
        });
});
</script>
于 2014-03-04T23:25:31.613 回答