Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何减少订阅操作符的数量并用不同的rxjs操作符替换_Angular_Rxjs_Angular2 Observables - Fatal编程技术网

Angular 如何减少订阅操作符的数量并用不同的rxjs操作符替换

Angular 如何减少订阅操作符的数量并用不同的rxjs操作符替换,angular,rxjs,angular2-observables,Angular,Rxjs,Angular2 Observables,尝试减少订阅的数量,并使用等效的flatMap\switchMap\do\taprxjs运算符来处理以下代码。 这是可行的,但我知道这不是最好的方法。 该守则的作用如下: 首先-进行凭证检查(usename和pass): A.如果它获取用户数据,它会重置登录尝试次数-将登录尝试次数重置为0,并路由到不同的路由。 B.如果不是(A)-增加登录尝试次数-将登录尝试次数增加1。服务将在增量后获取登录次数。根据它的检查-如果登录尝试>=3,那么它将生成CaptCha,这也将返回observable //

尝试减少订阅的数量,并使用等效的flatMap\switchMap\do\taprxjs运算符来处理以下代码。 这是可行的,但我知道这不是最好的方法。 该守则的作用如下: 首先-进行凭证检查(usename和pass): A.如果它获取用户数据,它会重置登录尝试次数-将登录尝试次数重置为0,并路由到不同的路由。 B.如果不是(A)-增加登录尝试次数-将登录尝试次数增加1。服务将在增量后获取登录次数。根据它的检查-如果登录尝试>=3,那么它将生成CaptCha,这也将返回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)));
} 

试着这样做:

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

我个人并不反对多个
。如果你的RXJS调用实际上不应该被链接,那么订阅
。但是,如果你要打两个电话,是的,你应该一起打
concatMap

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

如果您发出一个http请求,并且不希望保持流打开,那么您就不必保留对任何RXJS调用的订阅。但是,如果您计划保持流打开,我建议使用
ngondestry
技术。 你可以阅读更多关于它的内容,也许你应该看看相同的概念,但告诉你相反的东西:)

此外,您还应该阅读更多关于您的
投手的信息。从技术上讲,这些应该是泡沫。实际学习的最好方法是自己编写代码,我建议您创建一个名为login$()的冷可观察对象,它完成您应该做的所有事情。仅对其调用.subscribe()将返回一个已完成的可观察值

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

由于其他人已经对如何编写代码发表了评论,所以我不会在这里编写代码,但您应该试一试

你有什么理由保留对订阅的引用吗?我假设你让他们在销毁时退订?正确-这就是原因-我在Ngondestory()事件中这么做谢谢你的评论-我确实使用Ngondestory技术(代码中没有提到)退订。