2017-02-20 29 views
2

Я работал над приложением в Angular2/CLI/NGRX, и до недавнего времени все шло хорошо. Я замечаю некоторые довольно большие всплески производительности, особенно с последовательными отправлениями в одном контейнере.Угловые проблемы с производительностью 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.

Проблема заключается в компоненте центра содержимого. У меня есть излучатель событий, который взаимодействует с компонентом контейнера. Он отправляет объект для «выбора» и запускает действие через диспетчер для обновления состояния с выбранным параметром. Первые две клики работают отлично, а затем вы начинаете замечать некоторое серьезное энергопотребление, когда продолжаете нажимать на разные области в дочерних компонентах. Это похоже на то, что диспетчер, похоже, увяз.

Я пробовал несколько вещей, таких как использование combLatest() и других инструментов, чтобы уменьшить нагрузку на обновления, однако это, похоже, еще хуже. В настоящее время способ загрузки приложений выглядит следующим образом:

Load Assessment -> After Load Assessment Effect -> Select Assessment -> After Load Selected Assessment Effect 

У любого другого проблемы с производительностью? Это что-то не связанное с NGRX и тем, как у меня есть настройки? В основном я использовал пример приложения NGRX в качестве отправной точки для установки моей установки.

Редактировать

Вот хронология представление проблема у меня. Это похоже на то, что событие click становится экспоненциально длиннее?

Timeline

Edit 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

ну, магазин-devtools должен быть отключен при производстве. – maxisam

+0

Я видел несколько историй о других компаниях, оставляющих их включенными в мир Реакт. Используя некоторые инструменты, доступные через их API. Я думаю, что главная проблема сейчас - это наши устаревшие сервисы, которые любят возвращать мир, когда нам нужен только небольшой кусочек. – Aric

+0

Вау! Я не могу поверить, как быстро это сейчас! Я начал думать, что совершил огромную ошибку, используя ngrx; какое облегчение * фух * – Kesarion