1

Ember.js を使用して、Server-Sent Events を使用してページングを実装するコントローラーを追加および更新するアプリケーションを構築しています。コントローラーの完全な実装を以下に示します。

    App.endpointsDisponiblesClass = Ember.ArrayController.extend({
    loading: true,
    completeList:[
         /*
         App.Endpoint.create({
             id: 1,
             id_manufacturer: 1,
             id_model: 1,
             mac_address: '00:11:22:33:44:55',
             last_known_ipv4:   '10.0.0.1',
             last_scanned:      '2012-12-31',
             last_configured:   null
         }),
         */
    ],
    content:    [],
    offset: null,
    limit:  10,
    displaySlice: function(offset) {
        if (offset >= this.completeList.length)
            offset = this.completeList.length - 1;
        if (offset < 0) offset = 0;
        offset = offset - (offset % this.get('limit'));
        if (this.get('offset') == null || offset != this.offset) {
            var slice = this.completeList.slice(offset, offset + this.get('limit'));
            this.set('offset', offset);
            this.set('content', slice);             
        }
    },
    displayStart: function() { this.displaySlice(0); },
    displayPrevious: function() { this.displaySlice(this.offset - this.limit); },
    displayNext: function() { this.displaySlice(this.offset + this.limit); },
    displayEnd: function() { this.displaySlice(this.completeList.length); },
    startPosition: function() {
        return this.get('offset') + 1;
    }.property('offset'),
    endPosition: function() {
        var pos = this.get('offset') + this.get('limit');
        if (pos > this.completeList.length)
            pos = this.completeList.length;
        return pos;
    }.property('offset', 'limit'),
    displayRefresh: function() {
        console.debug('displayRefresh');
        var offset = this.get('offset');
        this.set('offset', null);
        this.displaySlice(offset);
    }.observes('completeList.@each')
});
App.endpointsDisponibles = App.endpointsDisponiblesClass.create();

completeList 要素には、ページをめくりたい要素の完全なリストが含まれており、そのうちの 1 つがコメントとしてリストされています。私の実装では、完全なリストのスライスを ArrayController サブクラスの 'content' 要素に割り当てることでページングを実行します。さらに、[次へ]、[戻る] などのボタンを表示するさまざまなビューから呼び出されるヘルパー メソッドがいくつかあります。

モデル リストをレンダリングするテンプレート フラグメントは次のようになります。

{{#view tagName="tbody"}}
{{#each App.endpointsDisponibles}}
<tr class="neo-table-data-row">
    <td class="neo-table-data-row">{{view Ember.Checkbox checkedBinding="isSelected"}}</td>
    <td class="neo-table-data-row">{{mac_address}}</td>
    <td class="neo-table-data-row"><a target="_blank" {{bindAttr href="adminUrl"}}>{{last_known_ipv4}}</a></td>
    <td class="neo-table-data-row">{{name_manufacturer}}</td>
    <td class="neo-table-data-row">{{view Ember.Select
        contentBinding="modelSelect"
        optionValuePath="content.id_model"
        optionLabelPath="content.name_model"
        valueBinding="id_model"
        disabledBinding="App.endpointScanController.scanInProgress"}}</td>
</tr>
{{else}}
<tr class="neo-table-data-row">
    <td class="neo-table-data-row" colspan="7">No endpoints have been discovered or loaded.</td>
</tr>
{{/each}}
{{/view}}

サーバーからの JSON メッセージを解析する onmessage ハンドラーを使用して EventSource を準備し、completeList で必要に応じてモデルを追加/更新/削除して、completeList を更新します。私は displayRefresh() で completeList.@each を観察しているので、最後のページを表示してモデルが追加された場合、または表示されたモデルの 1 つが削除された場合に、ページ スライスが更新されます。これまでのところ、それは完全に機能します。

問題は、メッセージが挿入をトリガーする時間の半分で、テンプレートの再レンダリングがユーザーにひどく見えることです。テンプレートが空になり、約 1 秒間空のままになり、適切なコンテンツが再入力されます。残りの半分の時間では、テンプレートの内容は、空にしたり補充したりせずにスムーズに更新されます。これは私が望んでいることです。SSE メッセージ ストリームはバースト性があります。数秒間アイドル状態になった後、1 秒以内に 5 ~ 6 個のメッセージを送信し、このサイクルが繰り返されます。醜いレンダリングは、Firefox と Google Chrome の両方で確認されています。

Firefox に Firebug をインストールし、コンソールからコントローラー メソッドを呼び出すことができます。これを行うと、SSE の場合とまったく同じように動作します。リフレッシュがスムーズな場合もあれば、テンプレートの空と再充填が表示される場合もあります。

テンプレートのレンダリングが一貫してスムーズになるようにするにはどうすればよいですか?

4

1 に答える 1