私はAngular2/CLI/NGRXのアプリケーションで作業してきましたが、最近までうまくいっています。私は、同じコンテナ内での連続したディスパッチで、特にパフォーマンスのかなり大きなスパイクに気付いています。Angular2 NGRXのパフォーマンスに関する問題
public appEnvironment$: Observable<IEnvironment>;
public assessment$: Observable<IAssessment>;
public assessmentComments$: Observable<ICommentActivity[]>;
public assessmentEvidence$: Observable<IEvidenceActivity[]>;
public assessmentIssues$: Observable<IIssueActivity[]>;
public assessmentSurvey$: Observable<ISurvey>;
public assessmentUsers$: Observable<ISystemUser[]>;
public assessmentSelectedNode$: Observable<ISurveyChildNode>;
constructor(private _store: Store<fromDomain.State>, private _route: ActivatedRoute) {
this.appEnvironment$ = _store.select(fromDomain.getEnvironment).share();
this.assessment$ = _store.select(fromDomain.getAssessment).share();
this.assessmentComments$ = _store.select(fromDomain.getAssessmentComments).share();
this.assessmentIssues$ = _store.select(fromDomain.getAssessmentIssues).share();
this.assessmentEvidence$ = _store.select(fromDomain.getAssessmentEvidence).share();
this.assessmentSurvey$ = _store.select(fromDomain.getAssessmentSurvey).share();
this.assessmentUsers$ = _store.select(fromDomain.getAssessmentUsers).share();
this.assessmentSelectedNode$ = _store.select(fromDomain.getAssessmentSelectedNode).share();
this.openAssessmentId = _route.snapshot.params['id'];
this._store.dispatch(new LoadAssessmentAction(this.openAssessmentId));
}
また、上記は、したがって、複数のコンポーネント(全体で共有子コンポーネントとそのデータをロードするために必要なすべての状態の選択であることは注目に値します:たとえば
は、私は次のように定義していると言うことができます。 share())は次のようなものです:
<opt-drawer-index
#drawerShow
[leftHeading]="'Survey Info'"
[leftIcon]="'fa-bars'"
[rightHeading]="'Assessment Details'"
[onForceChange]="assessmentSelectedNode$ | async">
<section drawer-left-content>
<opt-assessment-show-survey-info
[appEnvironment]="appEnvironment$ | async"
[assessment]="assessment$ | async"
[assessmentUsers]="assessmentUsers$ | async"></opt-assessment-show-survey-info>
</section>
<section drawer-content>
<opt-assessment-show-content
[appEnvironment]="appEnvironment$ | async"
[assessment]="assessment$ | async"
[assessmentSurvey]="assessmentSurvey$ | async"
(selectedNode)="changeSelectedNode($event)"></opt-assessment-show-content>
</section>
<section drawer-right-content>
<opt-assessment-show-details
[activeNode]="assessmentSelectedNode$ | async"
[appEnvironment]="appEnvironment$ | async"
[assessment]="assessment$ | async"
[assessmentComments]="assessmentComments$ | async"
[assessmentEvidence]="assessmentEvidence$ | async"
[assessmentIssues]="assessmentIssues$ | async"
[assessmentUsers]="assessmentUsers$ | async"></opt-assessment-show-details>
</section>
</opt-drawer-index>
初期荷重は大きく、うまくいきます。私はフリーズ状態をアクティブにしており、状態内に突然変異は起こっていない。すべてのコンポーネントはOnPush戦略も利用しています。
問題は中央のコンテンツコンポーネント内にあります。私には、コンテナコンポーネントと通信するイベントエミッタがあります。それはオブジェクトを '選択する'まで送信し、ディスパッチャを介してアクションをオフにして、選択したオプションで状態を更新します。最初のカップルのクリックは素晴らしい走りを見せています。その後、子コンポーネント全体のさまざまな領域をクリックし続けると、重大な電力消費に気付き始めます。ディスパッチャがうごめいているようです。
combineLatest()と他のツールを使用してアップデートの負担を軽減するなど、いくつかのことを試しましたが、問題が悪化したようです。現在、アプリケーションがデータをロードする方法は次のとおりです。
Load Assessment -> After Load Assessment Effect -> Select Assessment -> After Load Selected Assessment Effect
他の人がパフォーマンスの問題に遭遇しましたか?それはNGRXに無関係なもので、私は物事をセットアップする方法ですか?私は主に、NGRXのサンプルアプリケーションを、セットアップのレイアウト方法のリファレンスポイントとして使用しました。
編集
ここに私がいる問題のタイムライン表現です。 Clickイベントが指数関数的に長くなっているようです。
編集私は再度選択使用して、ここで、後続のクリックした後ハングしているページのエフェクトです午前2
:
import {Injectable} from "@angular/core";
// NGRX
import {Actions, Effect} from "@ngrx/effects";
import {Action} from "@ngrx/store";
// Services
import {AssessmentService} from "./assessment.service";
import {SurveyService} from "../survey/survey.service";
import {SystemUserService} from "../system-user/system-user.service";
// Observable and operators
import {Observable} from "rxjs/Observable";
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/concatMap';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/map';
// Misc
import * as assessment from './assessment.actions';
import * as assessmentNav from './navigation/assessments-navigation.actions';
@Injectable()
export class AssessmentEffects {
constructor(private actions$: Actions, private assessmentsService: AssessmentService,
private surveyService: SurveyService, private systemUserService: SystemUserService) { }
@Effect()
effLoadAssessment$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT)
.map((action: assessment.LoadAssessmentAction) => action.payload)
.switchMap(guid => {
return this.assessmentsService.getAssessment(guid)
.map(v => new assessment.LoadAssessmentCompleteAction(v));
});
@Effect()
effAfterLoadAssessment: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT_COMPLETE)
.map((action: assessment.LoadAssessmentCompleteAction) => action.payload)
.mergeMap(theAssessment => {
return [
new assessment.LoadAssessmentSurveyAction(theAssessment.surveyID),
new assessmentNav.AssessmentNavAddAction(theAssessment),
new assessment.LoadAssessmentUserAction(theAssessment.instanceOwner_SystemUserID)
];
});
@Effect()
effLoadAssessmentComments$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT_COMMENTS)
.map((action: assessment.LoadAssessmentCommentsAction) => action.payload)
.switchMap(multiRequest => {
return this.assessmentsService
.getAssessmentComments(multiRequest.assessmentId, multiRequest.type, multiRequest.nodeId)
.map(v => new assessment.LoadAssessmentCommentsCompleteAction(v));
});
@Effect()
effAfterSelectedNode$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.SELECT_ASSESSMENT_NODE)
.map((action: assessment.SelectedNodeAction) => action.payload)
.mergeMap(theNode => {
return [
new assessment.LoadAssessmentCommentsAction({
type: 'Comments',
nodeId: theNode.id,
assessmentId: theNode.assessmentId
}),
new assessment.LoadAssessmentIssuesAction({
type: 'Issues',
nodeId: theNode.id,
assessmentId: theNode.assessmentId
}),
new assessment.LoadAssessmentEvidenceAction({
type: 'Attachments',
nodeId: theNode.id,
assessmentId: theNode.assessmentId
})
];
});
@Effect()
effLoadAssessmentIssues$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT_ISSUES)
.map((action: assessment.LoadAssessmentIssuesAction) => action.payload)
.switchMap(multiRequest => {
return this.assessmentsService
.getAssessmentIssues(multiRequest.assessmentId, multiRequest.type, multiRequest.nodeId)
.map(v => new assessment.LoadAssessmentIssuesCompleteAction(v));
});
@Effect()
effLoadAssessmentEvidence$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT_EVIDENCE)
.map((action: assessment.LoadAssessmentEvidenceAction) => action.payload)
.switchMap(multiRequest => {
return this.assessmentsService
.getAssessmentEvidence(multiRequest.assessmentId, multiRequest.type, multiRequest.nodeId)
.map(v => new assessment.LoadAssessmentEvidenceCompleteAction(v));
});
@Effect()
effLoadAssessmentUser$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT_USER)
.map((action: assessment.LoadAssessmentUserAction) => action.payload)
.concatMap(guid => {
return this.systemUserService.getSystemUser(guid)
.map(v => new assessment.LoadAssessmentUserCompleteAction(v));
});
@Effect()
effLoadAssessmentSurvey$: Observable<Action> = this.actions$
.ofType(assessment.ActionTypes.LOAD_ASSESSMENT_SURVEY)
.map((action: assessment.LoadAssessmentSurveyAction) => action.payload)
.switchMap(guid => {
return this.surveyService.getSurvey(guid)
.map(v => new assessment.LoadAssessmentSurveyCompleteAction(v));
});
}
セレクタを作成するのに 'reselect'を使用していますか? – cgatian
あなたのエフェクトを共有できますか? – Maxime
@cgatianはい私は 'reselect'を使って状態のセレクタを作成しています。 @Maxime私は減速の原因となったページのエフェクトを添付しました。この州の特定のスライスが大きすぎるのかどうか疑問に思います。我々は、サービスから戻って利用しない大量のデータを取得し、 'Object.assign'を実行して、変化する状態の部分をリセットしています。状態をさらに細かくスライスすることは有益でしょう。 – Aric