dojo模式 - 何时使用set / watch以及何时使用notify / observe?

时间:2013-05-21 18:08:13

标签: model-view-controller dojo

我正在围绕有状态对象和Observable商店的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;
    },

1 个答案:

答案 0 :(得分:1)

  

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

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

  

但是如果我的观察者呼叫设置我得到了一个&#34;查询已经过时,你必须在任何数据修改之前观察()查询&#39;&#34;错误我无法调和。

您不应watch拨打notifyobserve拨打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>