Я работал над приложением в 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 становится экспоненциально длиннее?
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));
});
}
Вы используете 'reselect' для создания ваших селекторов? – cgatian
Можете ли вы поделиться своими эффектами? – Maxime
@cgatian Да, я использую 'reselect' для создания селекторов для частей состояния. @Maxime Я добавил эффекты для страницы, что привело к замедлению. Мне интересно, становится ли этот конкретный срез государства слишком большим. Мы получаем тонну данных, которые мы не используем обратно из служб, и я запускаю «Object.assign» для сброса частей состояния, которые меняются.Возможно, было бы полезно дополнительно разрезать состояние на более мелкие кусочки. – Aric