Подписка, вызываемая несколько раз, открывается дважды после изменения состояния с помощью Ngrx - Angular - PullRequest
1 голос
/ 21 января 2020

Диалог открывается несколько раз, потому что подписка вызывается дважды / несколько раз после изменения состояния ngrx.

  1. Попытка с использованием takeUntil (loadingComplete) с loadComplete = new BehaviorSubject (false), но не работает с моей логикой c. Потому что по крайней мере однажды эта подписка должна быть вызвана после того, как состояние задания «ЗАВЕРШЕНО».

  2. Попытка с использованием take (1), так как я опрашиваю для получения статуса прогресса, не может быть получена после первой подписки при использовании дубля 1. Поэтому добавлен флаг isCompleteDialogOpened для управления диалоговым окном нескольких подписок, которое открывается один раз. Но каждый раз, когда вызывается подписка isCompleteDialogOpened остается! False в

    if(uploadStatus.jobStatus === 'COMPLETED' && !this.isCompleteDialogOpened)
    

даже после того, как я установил значение true при первой подписке в openUploadCompleteDialog (), вызов метода isCompleteDialogOpened is false при второй подписке, поэтому диалог открывается несколько раз.

 isCompleteDialogOpened = false;   // -->Init as false

 ngOnInit() {
            this.pollUploadStatus(); // --> Oninit call for subscription method
        }

 pollUploadStatus() { // --> uploadStore ngrx store when selectCurrentJob mutates this is subscribed
        this.uploadStore.select(selectCurrentJob)
            .pipe(filter(uploadJob => !!uploadJob && !!uploadJob.jobStatus))
            .subscribe((uploadJob) => { // --> Subscription called multiple times
                const uploadStatus = uploadJob.jobStatus;


                  // --> this.isCompleteDialogOpened remains false even if i set true when
                  // --> the dialog is opened on first subscription How to maintain the state 
                  // --> of 'isCompleteDialogOpened'  on each subscription so that when the second
                 // -->  subscription made it is set true and condition fails


                if (uploadStatus.jobStatus === 'COMPLETED' && !this.isCompleteDialogOpened) {
                    this.openUploadCompleteDialog(); // --> upload dialog box is called twice
                }             
    }


openUploadCompleteDialog(): void {

    this.isCompleteDialogOpened = true; // --> set true after dialog open on subscription

    const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
        data: ....
    });
    dialogRef.afterClosed().subscribe(result => {
        const message = this.translate
            .instant('upload-success');
        this.openUploadSnackBar(true, message);
        this.router.navigateByUrl('car/add-update/car-history');
    });
}

 ngOnDestroy() {
        this.uploadStore.dispatch(stopPolling({}));
        this.destroy$.next();
        this.destroy$.complete();
    }

Может быть дубликатом Как остановить подписку после того, как ответ на службу / магазин имеет определенный аргумент / значение , но takeUntil не работает для моей логики c

Есть ли способ открыть диалоговое окно один раз после изменения состояния на «ЗАВЕРШЕНО» на основе флага, если это флаг, как поддерживать состояние для каждой подписки или чего-то еще. Любая помощь будет отличной.

Использование Angular8, Rx js 6.5.2.

Ответы [ 2 ]

1 голос
/ 21 января 2020

Не знаю, почему select срабатывает слишком часто, но здесь

 pollUploadStatus() { // --> uploadStore ngrx store when selectCurrentJob mutates this is subscribed
        this.uploadStore.select(selectCurrentJob)
            .pipe(filter(uploadJob => !!uploadJob && !!uploadJob.jobStatus))

добавление distinctUntilChanged (возможно, с пользовательским сопоставлением, так как поток содержит объекты, а не примитивы) в канал после filter, должен решить проблему.

0 голосов
/ 21 января 2020

Только для информации: когда я возвращаюсь на какую-то другую вкладку, эта подписка остается отписанной, и это проблема. DistinctUntilChanged помог мне найти главную проблему путем печати журналов и удаления этих флагов, а также сделал мой код чистым .

private destroy$ = new Subject<void>();

pollUploadStatus() {
    this.uploadStore.select(selectCurrentJob)
        .pipe(filter(uploadJob => !!uploadJob && !!uploadJob.jobStatus),
        distinctUntilChanged((prev, curr) =>
            prev.jobStatus.percentComplete === curr.jobStatus.percentComplete),
            takeUntil(this.destroy$))
        .subscribe((uploadJob) => {
            const uploadStatus = uploadJob.jobStatus;
            if (uploadStatus.jobStatus === 'COMPLETED') {
                this.openUploadCompleteDialog(); --> this.router.navigateByUrl('car/add-update/car-history');
            }
        });
}

ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
}
...