【问题标题】:how to decrease the amount of subscribe operators and replace with a different rxjs operators如何减少订阅运算符的数量并用不同的 rxjs 运算符替换
【发布时间】:2019-11-10 17:06:21
【问题描述】:

尝试减少 订阅数并使用等效的flatMap\switchMap\do\tap rxjs下面提到的代码的运算符。 它正在工作,但我知道这不是最好的方法。 代码的作用如下: 首先 - 有一个凭证检查(用户名和通行证): A. 如果它获取用户数据,它会 resetLoginAttempts - 将登录尝试次数重置为 0 并路由到不同的路由。 B. 如果不是 (A) - 它增加登录尝试次数 - 将登录尝试次数增加 1。服务在增加后取回登录次数。根据它检查 - 如果登录尝试 >= 3 则它生成验证码,它也返回 observable。

//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)));
} 

【问题讨论】:

  • 您是否有任何理由保留对订阅的引用?我假设你让他们在销毁时取消订阅?
  • 正确 - 这就是原因 - 我在 ngOnDestroy() 事件中这样做

标签: angular rxjs angular2-observables


【解决方案1】:

如果您的 RXJS 调用不应该被链接起来,我个人不会反对多个 .subscribe。但是,如果您应该拨打 2 个电话,是的,您应该一起 concatMap

另一件可以清理代码的事情是知道流是否真正完成。在我看来,这是 RXJS 的一个缺陷,不知道你的调用是 1 次的,还是实际上是一个流。

如果您发出一个 http 请求并且不希望保持流打开,那么您不必保留对任何 RXJS 调用的订阅。但是,如果您打算保持流打开,我会推荐 ngOnDestroy 技术。 你可以阅读更多关于它的信息"Don't forget to unsubscribe",也许你应该看看同样的概念,但告诉你相反的东西:"Don't Unsubscribe" :)

另外,您应该阅读更多关于您的throwError 的信息。从技术上讲,这些应该会冒泡。实际学习的最佳方法是自己编写代码,我建议您创建一个名为 login$() 的冷可观察对象,它可以完成您应该做的所有事情。只有在它上面调用 .subscribe() 才会返回一个 completed observable。

由于其他人已经评论过如何编码,我不会在这里编码,但你应该试一试!

【讨论】:

  • 感谢您的 cmets - 我确实使用 ngOnDestroy 技术(代码中未提及)来取消订阅。
【解决方案2】:

试试这样的:

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?
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多