RxJS |Как мне перехватить и потерпеть неудачу в канале, используя concatMap - PullRequest
1 голос
/ 25 июня 2019

Я пытаюсь использовать concatMap, чтобы позволить мне запускать запросы в последовательном порядке без необходимости визуально подписываться на каждый отправляемый запрос.

Все работает нормально, однако при возникновении ошибки он продолжает работать через канал, который я не хочу.

Если это не удается, я просто хочу отменить все запросы, остановить его выполнение и что-то отобразить. Я пытался catchError, однако, это не работает / делает то, что я хочу.

Возьмите этот пример ...

Я хочу сбросить пароль пользователя, после сброса пароля я хочу POST до конечной точки /password/resets, затем я хочу автоматически войти в систему пользователя, поэтому для этого я хочу отправить сообщение на /auth/login и Затем я хочу получить пользователя GET - /user, чтобы использовать его в приложении. Если запрос не удается на любом этапе. Я хочу остановить каналы и выдать общую ошибку, которая показана внизу вопроса.

this.userService.resetPassword(password)
.pipe(concatMap(() => this.authService.login(user.email, password)))
.pipe(concatMap(() => this.userService.me()))
.subscribe((user: User) => {
    this.userService.setUser(user);
});

Пример:

this.userService.resetPassword(password)
.pipe(concatMap(() => this.authService.login(user.email, password)))
<-- IF IT FAILS ON THE ABOVE / ANY REQUEST I WANT TO STOP ALL REQUESTS AND SHOW NOTIFICATION -->
.pipe(concatMap(() => this.userService.me()))
.subscribe((user: User) => {
    this.userService.setUser(user);
});

Ниже приведен фрагмент кода, который я хочу запустить при ошибке -

this.notificationService.notify('Unable to reset password, please try again.');

Ответы [ 3 ]

0 голосов
/ 25 июня 2019

Вы можете добавить catchError на тот же уровень concatMap? (Например:)

// also no need to put pipe for each piping. You can add a single one
this.userService.resetPassword(password)
  .pipe(concatMap(() => this.authService.login(user.email, password)),
        concatMap(() => this.userService.me()),
        catchError(err => throwError('error'))
  .subscribe((user: User) => {
    this.userService.setUser(user);
});

эта ошибка отлова должна получить любую ошибку, обнаруженную в пути, и отбросить ее назад. Если я не ошибаюсь. Если вы ловите его внутри concatMap, вы разрешаете этот innerObservable, но внешний продолжает работать. Поэтому вам нужно остановить верхний слой, чтобы он вел себя так, как вы хотите.

0 голосов
/ 25 июня 2019

То, как вы используете pipe и операторы rxjs, делает невозможным перехват.Оператор catchError может перехватывать исключения во всем канале, в котором он находится.

Не могли бы вы исправить это и попробовать еще раз?

yourCall().pipe(
    concatMap(() => otherCall()),
    concatMap(() => otherCall()),
    catchError( error => handleError())
).subscribe(result => doWhatYouWant());
0 голосов
/ 25 июня 2019

Вы можете использовать catchError https://blog.angular -university.io / rxjs-error-processing / Кроме того, вы можете связывать вызовы внутри одного канала () вместо того, чтобы повторять его.

Что-то вроде

this.userService.resetPassword(password)
.pipe(
    concatMap(() => this.authService.login(user.email, password).pipe(
        map(() => this.userService.me()),
        catchError(error => doSomething)))),
    ).subscribe((user: User) => {
    this.userService.setUser(user);
});
...