как уменьшить количество операторов подписки и заменить их другими операторами rxjs - PullRequest
0 голосов
/ 10 ноября 2019

Попытка уменьшить число подписок и использовать эквивалентные flatMap \ switchMap \ do \ tap rxjs операторов для упомянутыхкод ниже. Это работает, но я знаю, что это не лучший способ сделать это. Код действует следующим образом: во-первых - проверка учетных данных (имя пользователя и пароль): A. если он выбирает пользовательские данные, он resetLoginAttempts - сбрасывает число попыток входа в систему в 0 и направляет на другой маршрут. B. Если нет (A) - он увеличивает LoginAttempts - увеличивает количество попыток входа в систему на 1. Служба извлекает номер входа в систему после увеличения. В соответствии с этим он проверяет - если логин пытается> = 3, тогда он генерирует Captcha, который также возвращает наблюдаемый.

//loginSrv.Login - return observable of userData (json)
//sessionService.resetLoginAttempts - return observable of void 
//sessionService.increaseLoginAttempts - return observable of any (json)
//loginSrv.GetCaptcha - return observable of any (svg image)

subscriptions : Subscription[] = [];
login()
{
  this.subscriptions.push(this.loginSrv.Login(userName, password).subscribe(result =>
  {
    if (result &&  result.userData)
    {
      this.sessionService.resetLoginAttempts().subscribe();
      this.router.navigateByUrl('');
    }
    else
    {
        this.subscriptions.push(this.sessionService.increaseLoginAttempts().subscribe(result => 
        {
          if (result.loginAttempts >= 3)
          {
            this.generateCaptcha();
          }
        }, error => 
          {
                throwError(error))
          }
      ));
    }
  }, (error => throwError(error))
));
}


generateCaptcha()
{
  this.subscriptions.push(this.loginSrv.GetCaptcha().subscribe(response => 
    {
      this.captcha = response;
      this.setCaptchaImage();
    },  
    error => throwError(error)));
} 

Ответы [ 2 ]

2 голосов
/ 10 ноября 2019

Лично я ничего не имею против множественных .subscribe, если ваши вызовы RXJS на самом деле не должны быть связаны. Однако, если вы должны сделать 2 вызова, да, вы должны concatMap вместе.

Еще одна вещь, которая очистит ваш код, это знание того, завершится поток на самом деле или нет. На мой взгляд, это недостаток в RXJS, потому что я не знаю, является ли сделанный вами вызов однократным или потоковым.

Если вы делаете один http-запрос и не ожидаете сохранить потокоткрыт, то вам не нужно сохранять подписку ни на один из ваших вызовов RXJS. Однако, если вы планируете держать поток открытым, я бы порекомендовал метод ngOnDestroy. Вы можете прочитать больше об этом «Не забудьте отписаться» и, возможно, вам стоит взглянуть на ту же концепцию, но сказать вам обратное: «Не отписываться» :)

Кроме того, вы должны прочитать немного больше о вашем throwError. Они должны технически пузыриться. Лучший способ научиться это самому кодировать, я бы порекомендовал вам создать холодную наблюдаемую систему с именем login $ (), которая делает все, что вы должны делать. Только вызов .subscribe () для него вернет завершено наблюдаемый.

Так как другие люди уже прокомментировали, как кодировать, я не буду здесь кодировать, но вы должны дать еговыстрел!

0 голосов
/ 10 ноября 2019

Попробуйте что-то вроде этого:

this.login$ = this.loginServ.Login(userName, password).pipe(
  map(result => result.userData),
);

this.login$.pipe(
  filter(login => !login),
  tap(() => this.sessionService.increaseLoginAttempts()), // void method
);

this.login$.pipe(
  filter(Boolean),
  tap(() => this.sessionService.resetLoginAttempts()), // void method
  tap(() => this.router.navigateByUrl('')),
);

this.captcha$ = this.sessionService.loginAttempts$.pipe( // observable value
  filter(loginAttempts => loginAttempts >= 3),
  switchMap(() => this.loginServ.GetCaptcha()),
  // maybe setCaptchaImage() here since no idea what it does. maybe you can use async pipe for it?
);
...