0

うまく説明できてないかも…

私はそよ風 js を使用してエンティティを具体化していますが、そのエンティティには 100 近くの float フィールドが含まれています。これらは、4 つの個別部品と合計があり、これが 19 回繰り返される計算結果フィールドです。したがって、19 x 5 = 95 フィールドなので、「ほぼ 100」になります。

基本的には次のとおりです。

calculationResult1_materials 
calculationResult1_processes 
calculationResult1_packaging 
calculationResult1_transport 
calculationResult1_total 

calculationResult2_materials 
calculationResult2_processes 
calculationResult2_packaging 
calculationResult2_transport 
calculationResult2_total 

calculationResult3_materials 
etc...

明らかなように、「合計」フィールドには他の 4 つの部分の合計が含まれますが、そのフィールドだけにアクセスするレガシー システムがあるため保存され、誰かが合計を表示するたびに合計を計算する必要がなくなります。 .

Breeze はフィールドの合計を他のフィールドと同様に単純な観測対象として具体化するため、計算のために他の 4 つのフィールドのいずれかを再計算するたびに、4 つの個々の構成部分 (材料) を手動で再合計する必要があることを意味します。 、パッケージング、プロセス、トランスポート) を作成し、結果を表示する html ページの div にバインドされている「合計」オブザーバブルに結果を入れます。

これは機能しますが、これが最も効率的な方法ではない可能性があることに私は気づきました。明らかに、計算ごとに他の4つのフィールドを含む19個のcomputedObservableをビューモデルに個別に作成し、実際の「合計」オブザーバブルの代わりにそれにバインドできますが、たとえばフィールド名が変更された場合はコードを手動で更新することを意味します。

計算の他の 4 つの部分のいずれかが変更されたときに自動的に計算され、引き続きエンティティの一部であり、微風が後で変更を保存するように、何らかの方法でオブザーバブルを計算オブザーバブルとして再定義する方法はありますか?

4

2 に答える 2

2

私は計算されたKOを使用しません!

EntityAspect.propertyChanged代わりに、カスタム イニシャライザで、EntityType のプロトタイプに再計算関数を追加してBreeze イベントをサブスクライブします)。

これは、変更されたプロパティの名前に基づいて合計を更新するパターンを理解すれば、はるかに軽量 (1000 ではなく 1 つのメソッド) であり、パフォーマンスが向上し、保守が容易になります。

コードは次のようになります。

function calculationResultCtor() {/*... stuff in the ctor */ }

calculationResultCtor.recalcTotals(propertyName, newValue)
    /* do whatever based on the newValue and the propertyName 
       remember to use the parens required by KO observables
    */
}

function calculationResultInitializer(cr) {
   // listen for any property change in this calculationResult instance
   cr.entityAspect.propertyChanged.subscribe(function(args){
        var propName = args.propertyName;
        if (/_total/.test(propName)) return; // skip changes to total properties
        args.entity.recalcTotals(propName, args.newValue);
   });
}

metadataStore.registerEntityTypeCtor('CalculationResult', 
    calculationResultCtor, calculationResultInitializer);

これをより効率的にするためのさらに巧妙な方法 (たとえば、 をキーとする計算関数の辞書propertyName) を考えることができますが、どこに行くのかはおわかりでしょう。

私が心配している 1 つのこと (そして、それが問題である場合は、KO の計算されたアプローチでも問題になるでしょう) は、自動化されたプロセスが一度に多くのプロパティを更新する "propertyChanged" ストームと呼ばれるものです。

その解決策 - それが問題であり、私がそうであると言っているわけではない場合 - 嵐の間に終了するように再計算イベントをラッチし、それが終わったら、単一のパスですべての合計を再計算するだけですエンティティを通して。

重要なポイントは、私がどこから始めたかです: 何千もの KO 計算を作成しないでください! はい、計画ではエンティティごとに少なくとも 19 個の計算が追加されるため、1000 になります。わずか 53 個のエンティティ インスタンスで 1000 を超えることになります。これは良くありません。

于 2013-11-13T07:16:46.613 に答える
1

Breeze がデータを処理する方法を定義するアプリには、「model.js」のようなものが必要です。関数を公開configureMetadataStoreし、そこに関数を配置する必要があります。

function configureMetadataStore(metadataStore){
  metadataStore.registerEntityTypeCtor('MyContainerClassFromServerModel', null, thisClassInitializer);

その後thisClassInitializer、「実体化されたオブジェクト」と呼ばれる、何をするかを Breeze に指示する場所を定義する必要があります。

function thisClassInitializer(myObject){
  myObject.customTotal = ko.computed({
    read: function(){
      return myObject.materials() + myObject.processes() + myObject.packaging() + myObject.transport();
    },
    write: function(newValue){
      myObject.total(newValue);
    }
  });
}

これでうまくいくはずです。または、私の頭に浮かんだことは、次のように定義できます。

function thisClassInitializer(myObject){
  myObject.customTotal = ko.computed({
    var newValue = myObject.materials() + myObject.processes() + myObject.packaging() + myObject.transport();
    myObject.total(newValue);
    return newValue;
  });
}

違いは、最初のものは試してみないと保証できない (この ko バインディングに熟練していない) ことですが、もう 1 つはうまくいくと確信しています。

説明: このようなものを定義すると、Breeze がサーバーからのオブジェクトを監視可能なオブジェクトに「実体化」するたびに、初期化子も呼び出されます。このようにして、オブジェクトが持つフィールドを変更できます。通常、計算された値 (合計など) をそこに入れるので、サーバーにも保存する必要はありません。理想的には、追加情報を保持しないため、サーバーに「合計」は必要ありません。すべての情報は他の変数にあり、この値は計算できます。

于 2013-11-12T10:16:05.907 に答える