NodeJS PEAN验证应用程序:为什么我在使用pipe()时从Observable得到“undefined”(subscribe()工作,但我得到一个错误)?

ao218c7q  于 2023-08-04  发布在  Node.js
关注(0)|答案(1)|浏览(109)

bounty已结束.回答此问题可获得+50声望奖励。赏金宽限期13小时后结束。Rok Benko希望吸引更多的注意力这个问题:**请参阅下面的EDIT 2(特别是GIF来看看发生了什么).**赏金将奖励给一个谁会给予我一个解决方案,使我的auth guard开始在所有三种情况下正常工作:1)当我点击按钮时(当前工作),2)当我在搜索栏中键入URL时(当前不工作),3)当我刷新页面时(当前不工作)。我不明白为什么现在只有这一种方法有效。

我正在使用PEAN堆栈(即PostgreSQL - ExpressJS - Angular - NodeJS)构建一个身份验证应用程序。

问题

我的auth guard有问题:

  • 如果我使用subscribe(),我会在控制台中得到预期的结果。*✔ -工作 *
  • 如果我使用pipe(),我在控制台中得到undefined。* -不工作 *
    if-signed-in.guard.ts
import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { tap, map } from 'rxjs/operators';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);
    
  auth.getSignInStatusObserver().subscribe((res: any) => {
    console.log(res);
  });

  return auth.getSignInStatusObserver().pipe(
    tap((status) => {
      console.log(status);
    }),
    map((status) => {
      console.log(status);
      if (status) {
        if (status.success === true) {
          return true;
        } else {
          router.navigate(['/dashboard']);
          return false;
        }
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    })
  );
};

字符串

截图:

x1c 0d1x的数据

我所尝试的

我尝试在subscribe()中实现相同的逻辑:

if-signed-in.guard.ts

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  auth.getSignInStatusObserver().subscribe((res: any) => {
    if (res) {
      if (res.success === true) {
        return true;
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    } else {
      router.navigate(['/dashboard']);
      return false;
    }
  });
};


但我得到了以下错误:
src/app/auth/guards/if-signed-in.guard.ts:7:14 -错误TS2322:类型'(路由:ActivatedRouteSnapshot,状态:RouterStateSnapshot)=> void'不可分配给类型' CanActivateFn '。类型“void”不能分配给类型“boolean”|UrlTree| Observable<Boolean|网站Map|Promise<boolean| UrlTree>'。
7导出常量IfSignedIn:CanActivateFn =(route,state)=> {

提问

使用pipe()时,为什么从Observable获取undefined
编辑1

我已经尝试了@MatthieuRiegler建议的代码,但我仍然得到与上面屏幕截图完全相同的响应。

if-signed-in.guard.ts

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { filter, tap, map } from 'rxjs/operators';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  auth.getSignInStatusObserver().subscribe((res: any) => {
    console.log(res);
  });

  return auth.getSignInStatusObserver().pipe(
    filter((status) => status !== undefined),
    tap((status) => {
      console.log(status);
    }),
    map((status) => {
      console.log(status);
      if (status) {
        if (status.success === true) {
          return true;
        } else {
          router.navigate(['/dashboard']);
          return false;
        }
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    })
  );
};

编辑2

我的应用程序运行异常。现在我有以下代码:

if-signed-in.guard.ts

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth/auth.service';
import { inject } from '@angular/core';
import { filter, tap, map } from 'rxjs/operators';
import { Router } from '@angular/router';

export const IfSignedIn: CanActivateFn = (route, state) => {
  const auth = inject(AuthService);
  const router = inject(Router);

  return auth.getSignInStatusObserver().pipe(
    filter((status) => status !== undefined),
    tap((status) => {
      console.log('Tap: ', status);
    }),
    map((status) => {
      console.log('Map: ', status);
      if (status) {
        if (status.success === true) {
          return true;
        } else {
          router.navigate(['/dashboard']);
          return false;
        }
      } else {
        router.navigate(['/dashboard']);
        return false;
      }
    })
  );
};


如果我点击 * 编辑配置文件 * 按钮,一切都按预期工作。如果我在搜索栏中输入http://localhost:4200/profile/edit-profile,它看起来像是发送值有问题,因为我接收到undefined,而且因为filter()工作,所以我在控制台中没有得到任何东西。
同样的事情也发生在页面刷新上。看来身份验证保护在页面刷新时不起作用。

截图:


编辑3

我使用拦截器设置登录状态,如下所示:

sign-in-status.service.ts

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { AuthService } from 'src/app/auth/services/auth/auth.service';

@Injectable({
  providedIn: 'root',
})
export class SignInStatusService implements HttpInterceptor {
  intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(httpRequest).pipe(
      tap((event: HttpEvent<any>) => {
        if (event instanceof HttpResponse && httpRequest.url.endsWith('api/get-user') && event.status === 200) {
          this.authService.setSignInStatus({ success: true, response: event.body });
        }
      }),
      catchError((err: any) => {
        if (httpRequest.url.endsWith('api/get-user')) {
          this.authService.setSignInStatus({ success: false, response: err });
        }
        return throwError(() => err);
      })
    );
  }

  constructor(private authService: AuthService) {}
}

fafcakar

fafcakar1#

你的问题在别处。正如您所看到的,您得到一个undefined作为订阅的第一个值。
通过执行subscribe而不关闭它,它的使用寿命比CanActivateFn长。
我的猜测是,你正在经历一个竞争条件。您的observable发出的状态对于CanActivateFn来说太晚了。
你的getSignInStatusObserver不应该发出undefined,你过滤它pipe(filter(status => status !== undefined)).这应该解决你的问题!

相关问题