2017-08-23 7 views
0

私は1000個以上のデータ要素を読み込む非常に大きなコンポーネントを持っています。これらのデータ要素は、一度だけ呼び出されるサービス経由で生成されます。最初の実装では、コンポーネントが初期化されるたびにサービスが呼び出されました。これは問題があると思った場所です。そこで、私は祖父母コンポーネントで一度しか呼び出されない共有サービスを作成しました。次のように角の大きいコンポーネントローディング時間の改善

成分階層構造は以下の通りである:

  • AddComponent(祖父母)
    • Type1AddComponent
      • BlockComponent(1000+データ要素を有する成分)
    • Type2AddComponent
      • BlockComponent
    • Type3AddComponent
      • 分かるようBlockComponent

BlockComponentは、すべての3つのTypeComponentsで使用されています。 3つの異なるTypeComponentsに示されているBlockComponentのデータは同じです(ただしタイトル @Input)。 TypeComponentの最初の初期化はうまくロードされますが、それらの切り替え時には読み込み時間が3秒を超えるため、私は不合理だと思います。ロード時間を短縮する方法はありますか?

私は下に共有されているコードがたくさんあることを知っています。 webpackプロジェクトのために私がそうする方法を知っていれば私はPlunkerを作成します。

共有data.service.ts

import { Injectable } from '@angular/core'; 
import { DataResolver } from '../../blocking/data/data.resolver'; 
import { Data } from 'si-data-model'; 
import { Observable } from 'rxjs/Observable'; 
import { Logger } from 'ngx-data-utils'; 

@Injectable() 
export class DataService { 

    data: Data[] = []; // shared data 
    dataObs$: Observable<Data[]>; 
    logger: Logger; 
    completed = false; // used to signal whether the service has completed to components 

    constructor(private resolver: DataResolver, 
       logger: Logger) { 
    this.logger = logger; 
    } 

    ngOnInit() { 
    this.logger.debug('Data Service initialized.'); 
    } 

    ngOnDestroy() { 
    this.logger.debug('Data Service destroyed.'); 
    } 

    load() { 
    return this.resolver.resolve(); // retrieves the data elements from a web service 
    } 

    initData() { 
    this.dataObs$ = this.load(); 
    this.dataObs$.subscribe((res: Data[]) => { 
     this.data = res; 
     this.completed = true; 
    }); 
    } 

} 

add.component.ts

import { Component, OnDestroy, OnInit } from '@angular/core'; 
import { DataService } from '../../shared/data/data.service'; 

@Component({ 
    selector: 'add', 
    templateUrl: './add.component.html', 
    styleUrls: ['./add.component.scss'] 
}) 
export class AddComponent implements OnInit, OnDestroy { 

    radioUrl: string; 

    constructor(private service: DataService) { 
    console.log('Add component built'); 
    } 

    ngOnInit() { 
    this.service.initData(); 
    console.log('Add component initialized'); 
    } 

    ngOnDestroy() { 
    console.log('Add component destroyed'); 
    } 

} 

type1.component.ts

import { Component, OnDestroy, OnInit } from '@angular/core'; 

@Component({ 
    selector: 'type1', 
    templateUrl: './type1.component.html', 
    styleUrls: ['./type1.component.scss'] 
}) 
export class Type1Component implements OnInit, OnDestroy { 

    title = 'Add Block Stuff'; 

    constructor() { 
    console.log('Type1 component built'); 
    } 

    ngOnInit() { 
    console.log('Type1 component initialized'); 
    } 

    ngOnDestroy() { 
    console.log('Type1 component destroyed'); 
    } 

    onType1Change($event: any) { 
    console.log($event); 
    } 
} 

block.component.ts

import { Component, OnDestroy, OnInit, Output, EventEmitter, Input } from '@angular/core'; 
import { Logger } from 'ngx-data-utils'; 
import { Observable } from 'rxjs/Observable'; 
import { Data } from 'si-data-model'; 
import { DataService } from '../../shared/data/data.service'; 

@Component({ 
    selector: 'block', 
    templateUrl: './block.component.html', 
    styleUrls: ['./block.component.scss'] 
}) 

export class BlockComponent implements OnInit, OnDestroy { 

    dataLoaded = false; 
    labels = ['Label1', 'Label2', 'Label3', 'Label4', 
    'Label5']; 
    selected: any[] = []; 
    data1: string; 
    data2: string; 
    data3: string; 
    data4: string; 
    data5: string; 
    data6: string; 
    datas: Data[] = []; 
    @Output() change: EventEmitter<any> = new EventEmitter(); 
    @Input() title: string; 
    @Input() data: Data[]; 

    // private criteriaCodes = [6, 2, 3, 11, 29, 25]; 

    constructor(private logger: Logger, 
       private dataService: DataService) { 
       // TODO 
    } 

    ngOnInit() { 
    this.display(); 
    this.logger.debug('BlockComponent initialized.'); 
    } 

    ngOnDestroy() { 
    this.logger.debug('BlockComponent destroyed.'); 
    } 

    initData() { 
    this.dataService.data.forEach((dt: Data) => { 
     this.datas.push(dt); 
     this.dataLoaded = true; 
    }); 
    } 

    display() { 
    if (this.dataService.completed) 
     this.initData(); 
    } 

    propagateChange() { 
    this.change.emit(this.selected); // doesn't do anything yet 
    } 

} 

block.component.htmlあなたadd.component.tsデータが再度初期化されるたびにregettingされるように見えます

<div class="row" *ngIf="dataLoaded"> 
    <div class="row"> 
    <div class="col-md-4"> 
     <label>{{'DATA.BLOCK.LABEL1' | translate}}</label> 
     <select class="custom-select form-control" [(ngModel)]="data1" (change)="propagateChange()"> 
     <option *ngFor="let c of data[0].value">{{c.code}} - {{c.description}}</option> 
     </select> 
    </div> 
    <div class="col-md-4"> 
     <label>{{'DATA.BLOCK.LABEL2' | translate}}</label> 
     <select class="custom-select form-control" [(ngModel)]="data2" (change)="propagateChange()"> 
     <option *ngFor="let mt of data[1].value">{{mt.code}} - {{mt.description}}</option> 
     </select> 
    </div> 
    <div class="col-md-4"> 
     <label>{{'DATA.BLOCK.LABEL3' | translate}}</label> 
     <select class="custom-select form-control" [(ngModel)]="data3" (change)="propagateChange()"> 
     <option *ngFor="let pem of data[2].value">{{pem.code}} - {{pem.description}}</option> 
     </select> 
    </div> 
    </div> 
    <div class="row"> 
    <div class="col-md-4"> 
     <label>{{'DATA.BLOCK.LABEL4' | translate}}</label> 
     <select class="custom-select form-control" [(ngModel)]="data4" (change)="propagateChange()"> 
     <option *ngFor="let tt of data[3].value">{{tt.code}} - {{tt.description}}</option> 
     </select> 
    </div> 
    <div class="col-md-4"> 
     <label>{{'DATA.BLOCK.LABEL5' | translate}}</label> 
     <select class="custom-select form-control" [(ngModel)]="data5" (change)="propagateChange()"> 
     <option *ngFor="let cl of data[4].value">{{cl.code}} - {{cl.description}}</option> 
     </select> 
    </div> 
    <div class="col-md-4"> 
     <label>{{'DATA.BLOCK.LABEL6' | translate}}</label> 
     <input type="text"> 
    </div> 
    </div> 
</div> 
+1

plunkerを使用してについては、あなただけ(ちょうど '新しい選択し、Plunkerで| Angular')を生成アンギュラスニペットにコードを追加することができます。そしてあなたのコードを追加してください。それはSystemjsですが、それでもあなたの問題をデモする必要があります。 (Webpackの問題だと思わない限り) – DeborahK

+0

私はそれがウェブパックの問題だとは思わない。翻訳のようなものを取り除き、Plunkrを動作させるにはちょっと時間がかかりますが、それは1000行のコードを投稿するよりも優れています。 –

答えて

0

?それはそれを取得しています一度

initData() { 
    if (!this.data) { 
     this.dataObs$ = this.load(); 
     this.dataObs$.subscribe((res: Data[]) => { 
     this.data = res; 
     this.completed = true; 
     }); 
    } 
    } 

そして、それは、データを再ロードされません。

あなたはこれを行うことができます。

子コンポーネントに関しては、少なくとも1つがEVERY要素をループしており、データ配列の独自のコピーを作成しているようです。

initData() { 
    this.dataService.data.forEach((dt: Data) => { 
     this.datas.push(dt); 
     this.dataLoaded = true; 
    }); 

代わりに、ゲッターを使用してみてください:

export class BlockComponent implements OnInit, OnDestroy { 

    get datas(): Data[] { 
     return this.dataService.data; 
    } 

    // ... 

} 
+0

あなたの言っていることが分かります。プランナーなしでテストするのは難しい... addコンポーネントが初期化されるたびにデータを取得するのは事実ですが、子供はそうではありません。結局私はこれに対処します。今、問題は子どもの負荷時間にあります。 Webサービスが1回だけ呼び出されても、子を切り替えるには3秒以上かかります。私はあなたのコードを試して、前と同じ結果を得ました。 –

+0

私の更新された回答を参照してください。 – DeborahK

+1

また、10,000個の要素すべてをすぐにダウンロードする必要があるかどうかは疑問です。ユーザーは、その多くのデータを実際に視覚的に処理することはできません。あなたはまたそれを壊すことを検討し、時間の塊をダウンロードするだけでよいかもしれません。おそらくページングするか、ダウンロードする前にユーザーがフィルタ条件を選択できるようにしてください。 – DeborahK

関連する問題