0

observableArrayにバインドするテンプレートがあります

<ul data-bind="template: { name: 'defaultTemplate', foreach: itemsArray}"></ul>
...

そして、リンクをクリックして毎回データを更新する必要があります

<a data-bind="click: LoadData"><span>Refresh</span></a>

私のviewModelの最初のバージョン:

function viewModel (){  
    this.itmesArray = ko.observableArray([]);
    self = this;
    this.LoadData(){
        if('undefined' != typeof MusicArray )
            self.itmesArray.removeAll();
        LoadDataFromServerAsync(self.itmesArray);
    }   
    //ini
    LoadData();
    ...
}

しかし、問題は、データがサーバーから非同期でロードされることです。そのため、短い時間間隔でリンクを高速でクリックすると、データが観察可能な配列で複数回複製される可能性があります。したがって、更新するたびに新しい配列にデータをロードする必要があると思います。

次に、viewModelの2番目のバージョン:

function viewModel (){  
    this.itmesArray = ko.observableArray([]);
    self = this;
    this.LoadData(){
            if('undefined' != typeof MusicArray )
                self.itmesArray.removeAll();
            var tempArray = new Array();
            LoadDataFromServerAsync(tempArray);
            self.itmesArray(tempArray);
    }   
    //ini
    LoadData();
    ...
}

そして、新しい問題は、UIが配列の変更を感知できなかったことです。self.itmesArray(tempArray)は新しいobservableArrayオブジェクトを構築するようですが、テンプレートのバインドはまだ古いobservableArrayオブジェクトを追跡しています。これについてはよくわかりません。 。だから私は私の配列が変更されたことをテンプレート/UIバインディングに通知する方法を知りたいですか、または私の問題を修正するための他の回避策はありますか?

追加:jsFiddleのコード http://jsfiddle.net/zzcJC/10/

4

4 に答える 4

1

Geneが提案するように行うことができます。クライアント側ですべてを行うために、ロジックをカプセル化するヘルパー オブジェクトを作成できます。リクエストを起動し、レスポンスを取得し、リクエストを停止する「中止」メソッドを備えています (ユーザーがまだデータを待っている間に「更新」を押した場合)。 )、すべてのデータが到着したときにのみビューモデルを更新します。

jsFiddle を作成しました: http://jsfiddle.net/saurus/dE6S9/

これは、「setTimeout()」を使用して ajax 呼び出しをシミュレートし、タイムアウト ID を配列に格納し (ajax 呼び出しによって返された xhr を格納します)、「cancelTimeout()」を呼び出して呼び出しを中止します (「xhr.abort または似ている)。

于 2011-12-30T10:02:33.953 に答える
0

非同期モードでデータをロードしている場合、問題は行が

self.itmesArray(tempArray);

ずっと前に実行される

LoadDataFromServerAsync(tempArray);

サーバーからの新しいデータのロードが完了したため、空の配列をバインドし続けます。

これを修正するには、サーバーが新しいデータを返した後にバインディングを行う必要があります。たとえば、jquery を使用して ajax 呼び出しを行う場合、「成功」コールバックでビューモデルを更新する必要があります。これが私がそれを行う方法です:

    $.ajax({
      type: "POST",
      url: "ws.asmx/GetData",
      data: "{}",
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      processData: false,
      success: function(msg) {
           viewModel.itmesArray(msg);
      }
    });

これで問題が解決しない場合は、'LoadDataFromServerAsync' の実装を確認する必要があると思います。

于 2011-12-29T11:18:18.053 に答える
0

おそらく、重複するリクエストに対処する 1 つの方法は、クライアントにユーザー アクション カウンターを保持し、その値をサーバーに渡すことです。これは、サーバーが何を返すかを制御できることを前提としています。その後、古いユーザー アクション値を持つ応答を無視できます。サーバー データにアクセスできない場合でも、アクション カウンターの値を成功ハンドラーに貼り付けることで、このアプローチを使用できます。これがこのコードのスケッチです。(注意: テストされていません)

function viewModel() {
    var self = this;
    var actionCounter = 0;
    var items = ko.observableArray([]);


    // This is triggered by a user request
    this.handleUserAction = function() {
        self.clearData();
        self.loadData(0, ++actionCounter); // assume 0=root
    }

    this.clearData = function() {
        this.items.removeAll();
    }

    // return some handle of the next request, or null
    this.moreRequestsRequired = function(data) {
         ...
         return ...;
    }

    this.processData = function(data, reqNo) {
        // this is where you would append it to the array
        ...

        // this is where the recursive call could be made
        var handle = self.moreRequestsRequired(data);
        if (handle)
            loadData(handle, reqNo);
    }

    this.loadData = function(handle, n) {
        var reqNumber = n;
        $.ajax('server/request', {
            data: {dir: handle},
            success: function(data) {
                if (reqNumber == actionCounter)
                   processData(data);
            }
        });
    }
};
于 2011-12-29T18:42:58.043 に答える
0

したがって、私が正しく理解している場合は、「更新」をクリックすると、いくつかの ajax 呼び出しがトリガーされ、それらの呼び出しから返されたデータが古いデータを完全に置き換えます。

1 つの方法は、すべての通話が他の通話に対して独立して機能するかどうかを確認することです。たとえば、私がコメントですぐに提案したようなことをする:すべての呼び出しを別々にし、単一の呼び出しが新しいデータを返したら、配列から古いデータを削除して新しいデータを追加します。これは、異なる呼び出しによって返される要素を区別できることを前提としています。

もう 1 つの方法は、複数の呼び出しを完全に回避することです。終了するまで UI インタラクションをブロックすることができます (たとえば、jquery blockui プラグインなどを使用)。または、更新中にユーザーが引き続きインターフェイスを使用できるようにする場合は、一部がまだ処理中である間に新しいリクエストを開始することを単純に避けることができます。

どちらの方法でも一連のリクエストがいつ開始されるかを知る必要がありますが、これは簡単です。これは「LoadData」メソッドの開始時に発生します。すべてのリクエストがいつ終了したかを知ることはもう少し複雑です。おそらくもっと良い方法があります。そうでない場合は、カウンターを作成し、発行する ajax リクエストごとに 1 ずつ増やしてから、リクエストが終了するたびに新しいデータを「プッシュ」します。 observableArray で、カウンターをデクリメントします (jquery では、エラーが発生した場合でも呼び出されることが保証されているため、「完全な」コールバックを使用します)。「LoadData」の最初に (配列をクリアする前であっても) テストを追加します。

if (counter > 0) return;

「blockui」の方法を使用する場合は、カウンターをデクリメントした後、すべての「complete」コールバックでカウンターを確認する必要があります。カウンターがゼロの場合は、UI のブロックを解除する必要があります (「blockui」オプションは、viewModel で UI を実行しないようにするための作業が必要です。 )。

私がまだ何かを見逃していない限り...

于 2011-12-29T16:23:59.733 に答える