2016-08-12 20 views
0

大規模なデータセットと組み合わせてKnockoutJS foreachバインディングを使用する際に問題があります。現在、コンテナdivの「データ」バインディングは、データを取得するためにajax呼び出しを実行し、JSオブジェクトで解析し、各結果を可観測配列にプッシュする関数に設定されています。KnockoutJS - foreachバインディングの非同期読み込み

このアプローチは、私のデータセットが小さい(0-50)場合に効果的です。しかし、100以上のレコードを持つとすぐに、合計時間が劇的に増加します。データが処理されるとすぐに、すべての要素が解析されて配列に追加されるまで、ブラウザのスレッドは「ロックされ」ます。最後に、コンテンツをDOMにロードし、すべてのコンテンツを一度に読み込みます。

DOMに要素を遅延ロードすることでこれを修正する方法があるのだろうかと思います。具体的には、すべての要素が処理されるのを待つのではなく、処理中の各要素をレンダリングするようDOMに指示します。あなたは私はあなたができることの可能なアプローチの一つを説明するコードスニペットを投稿しませhave'veので

おかげ

+2

あなたは一緒に問題を再現jsfiddleやスニペットを置くことができます? – JohnnyHK

+1

ここで説明した手法を使用すると、大規模なデータセットで私のアプリのパフォーマンスが大幅に向上しました - http://www.knockmeout.net/2012/04/knockoutjs-performance-gotcha.html – dmoo

+0

https://github.com/brianmhunt/knockout -fast-foreach –

答えて

0

。 遅延ロードを処理できる方法でデータを戻すサーバーサイドコードを変更することができます。
次に、最後のajax呼び出しがデータを返す場合に、その関数内でフラグをチェックする関数を呼び出す間隔関数を持つ必要があります。次に、次のajaxを呼び出します。
あなたの応答データには、より多くのデータ、合計アイテムなどがあるかどうかを追跡するためのプロパティがあります.Ajax successコールバックアップデートでは、NextPageなどのリクエストデータを送信するために使用できる変数observablesより多くのデータを使用すると、setInterval関数をキャンセルします。以下は


あなたがこのアプローチを実装する方法のほんの一例である(未テスト)
JS:

var YourViewModel = function() { 
    var self = this ; 
    var loadMoreTimer; 
    self.IsMoreItems = ko.observable(false); 
    self.LoadingMoreInProcess = ko.observable(false); 
    self.CurrentPage = ko.observable(0); 
    self.Items = ko.observableArray([]); 

    self.AutomaticLoadItem = function() { 
     loadMoreTimer = setInterval(callLoadMore, 500); 
    } 

    function callLoadMore() { 
     if (self.IsMoreItems()) { 
     if (!self.LoadingMoreInProcess()) { 
      self.LoadMore(); 
     } 
     } 
    } 
    self.LoadMore = function() { 
     self.CurrentPage(self.CurrentPage() + 1); 
     self.LoadingMoreInProcess(true); 
     data = {requestPage : self.CurrentPage(), numberOfItem : 20, ...} 
     //your ajax call here 
     $.ajax({ 
      url:..., 
      type: ....,  
      data: data,  
      success: function(response){ 
      // here you check if there is more data left 
       if(response.isMoreData){ 
       // set it to false so the next ajax call can be executed. 
       self.LoadingMoreInProcess(false); 
       // map through your data and push each item into the observableArray 
       $.map(response.Items, function (item) { 
        self.Items.push(new ItemDetailViewModel(item)); 
        }); 
       }else{ 
       // if there is no more data stop the interval function. 
       clearInterval(loadMoreTimer); 
       } 
      }       

     }) 
    } 
    //Call to start lazy loading 
    self.AutomaticLoadItem(); 
} 

var ItemDetailViewModel = function (data){ 
    var self = this ; 
    self.Id = data.Id ; 
    self.Name = data.Name; 
    // ..... 
} 
関連する問題