每次用户注销时都会发送一个新的重复注销HTTP请求:Angular、RxJs 问题说明

每次用户注销时都会发送一个新的重复注销HTTP请求:Angular、RxJs 问题说明,angular,rxjs,jwt,rxjs-observables,nebular,Angular,Rxjs,Jwt,Rxjs Observables,Nebular,首先,让我首先说,我正在使用Angular 10和星云UI库作为前端,Node.js作为后端API,JWT和电子邮件/密码策略进行身份验证。我注意到,每次用户登录并注销而不刷新应用程序时,都会向服务器发出一个新的重复注销请求(发送多个http请求)。 如果在注销后刷新应用程序,问题就会消失。我不确定我是否跳过了一些东西,或者我只是不知道使用JWTs注销和重新登录的正确方法,但是我已经尝试了几天来解决这个问题,但没有成功,所以我渴望得到一些帮助 当前行为: 如果用户要多次登录并重新注销,向服务器发

首先,让我首先说,我正在使用Angular 10和星云UI库作为前端,Node.js作为后端API,JWT和电子邮件/密码策略进行身份验证。我注意到,每次用户登录并注销而不刷新应用程序时,都会向服务器发出一个新的重复注销请求(发送多个http请求)。 如果在注销后刷新应用程序,问题就会消失。我不确定我是否跳过了一些东西,或者我只是不知道使用JWTs注销和重新登录的正确方法,但是我已经尝试了几天来解决这个问题,但没有成功,所以我渴望得到一些帮助

当前行为:

如果用户要多次登录并重新注销,向服务器发出的注销请求将重复。无论您是否使用http侦听器(NbAuthJWTInterceptor或其他),此问题都会持续存在

预期行为:

如果用户要再次登录并注销,无论用户在不刷新应用程序的情况下重复这些步骤多少次,都不应向服务器发出多余的注销请求

复制步骤:

  • 用户第一次登录时,一切正常,并且在您注销时没有向服务器发出重复请求
  • 在未刷新应用程序的情况下,第二次重新登录和第二次注销后,向服务器发出的第二次注销请求将发送一个重复的注销请求(向服务器发送两个相同的注销请求)
  • 如果用户再次登录第三次,并且再次退出,则将向服务器发送3个注销请求(总共发送3个相同的请求)
  • 如果用户要再次登录并注销,将再次发送重复的注销请求,总共将发送4个相同的注销请求。这种情况将无限期地继续下去
  • 以下是“我的开发工具网络”选项卡上关于这4个步骤的屏幕截图(在登录和注销4次之后):

    相关代码: 在客户端,我有header.component.ts文件,从该文件启动注销过程:

    ...
    ngOnInit() {
        // Context Menu Event Handler.
        this.menuService.onItemClick().pipe(
          filter(({ tag }) => tag === 'my-context-menu'),
          map(({ item: { title } }) => title),
        ).subscribe((title) => {
          // Check if the Logout menu item was clicked.
          if (title == 'Log out') {
    
            // Logout the user.
            this.authService.logout('email').subscribe(() => {
              // Clear the token.
              this.tokenService.clear()
              // Navigate to the login page.
              return this.router.navigate([`/auth/login`]);
            });
    
          }
          if (title == 'Profile') {
            return this.router.navigate([`/pages/profile/${this.user["_id"]}`]);
          }
        });
    }
    ...
    
    在服务器端,有一个注销API路由返回成功的200响应:

    // Asynchronous POST request to logout the user.
    router.post('/sign-out', async (req, res) => {
        return res.status(200).send();
    });
    

    您正在另一个订阅中订阅。这会导致每次调用
    This.menuService.onItemClick()
    时都进行另一次订阅

    您需要通过使用适当的Rxjs操作符(exhaustMap、concatMap、switchMap、mergeMap)来使用平坦化策略

    在您的情况下,我会像这样重构(不要忘记取消订阅Ngondestory中的每个订阅)


    `

    非常感谢您!它的工作与一些调整!
    const titleChange$ = this.menuService.onItemClick()
      .pipe(
        filter(({ tag }) => tag === 'my-context-menu'),
        map(({ item: { title } }) => title)
      );
    
    this.logOutSubscription = titleChange$.pipe(
      filter((title) => title == 'Log out'),
      exhaustMap((title) => this.authService.logout('email')),
      tap(() => {
        this.tokenService.clear()
        this.router.navigate([`/auth/login`]);
    })
    .subscribe();
    
    this.profileNavSubscription = titleChange$
      .pipe(
        filter((title) => title == 'Profile'),
        tap(title => {
          this.router.navigate([`/pages/profile/${this.user["_id"]}`])
        })
       .subscribe();