2017-02-20 77 views
2

我一直在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)); 
} 

另外值得一提的是,以上是所有加載在多個部件共享的子組件和它們的數據所需的狀態選擇(因此。分享())類似:

<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示例應用程序作爲如何佈置我的設置的參考點。

編輯

這裏是我有問題的時間表表示。就好像點擊事件呈指數級增長一樣?

Timeline

編輯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)); 
 
    }); 
 
}

+0

您是否使用'reselect'來創建您的選擇器? – cgatian

+0

你能分享你的效果嗎? – Maxime

+0

@cgatian是的,我正在利用'reselect'來創建狀態片段的選擇器。 @Maxime我附加了導致頁面放緩的頁面效果。我想知道這個州的這個特定部分是否變得太大了。我們確實得到了大量我們沒有從服務中獲得的數據,而且我正在使用Object.assign來重置那些發生變化的狀態。將狀態進一步分成更小的部分可能是有益的。 – Aric

回答

6

放緩實際上是相關的到@ngrx/store-devtools。從應用程序中刪除模塊後,速度非常快。我們希望能夠使用該工具進行快照和重播狀態,但我不確定我們可以在性能受到影響的情況下繼續下去。

+0

好吧,store-devtools應該禁用生產。 – maxisam

+0

我已經看到其他公司在React世界中啓用它們的一些故事。利用其API提供的一些工具。我認爲現在的主要問題是我們的傳統服務在我們只需要一小段時間時就想要回歸世界。 – Aric

+0

哇!我無法相信現在有多快!我開始認爲我使用ngrx犯了一個大錯誤;多麼舒心* phew * – Kesarion