代码之家  ›  专栏  ›  技术社区  ›  xarielah

从app.config.ts调用时,BehaviorSubject不会更新

  •  1
  • xarielah  · 技术社区  · 9 月前

    TL;DR-解决方案:

    我使用的是订阅,而不是将值管道传输到APP_INTIALIZER。此外,我注册了两次UserService,一次是作为单例(它应该是),第二次是在Header组件中注册,它本身就是UserService的一个新实例。

    =======================

    我正在通过app.config.ts调用我的UserService:

    export const appConfig: ApplicationConfig = {
    providers: [
        provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes),
        provideHttpClient(),
        provideAnimationsAsync(),
        {
          provide: APP_INITIALIZER,
          useFactory: (userService: UserService) => {
            return () => userService.getSessionMock();
          },
          deps: [UserService],
          multi: true,
        },
      ],
    };
    

    用户服务:

      public user$ = new BehaviorSubject<AuthUser | null>(null);
    
      constructor(private readonly http: HttpClient) {}
    
      public getSession() {
        return this.http
          .get<SessionUser>('https://localhost:7298/api/auth/session', {
            withCredentials: true,
          })
          .subscribe((user) => {
            (user as AuthUser).isAuthenticated = true;
            this.user$.next(user as AuthUser);
          });
      }
    

    即使我使用模拟用户,这也不起作用。 当我在组件本身上从ngOnInit运行代码时,它就起作用了。

    使用数据的HeaderComponent:

    export class HeaderComponent {
      userService: UserService = inject(UserService);
      currentUser$ = this.userService.user$;
    
      ngOnInit() {
        this.currentUser$.subscribe((user) => console.log(user));
      }
    }
    

    header.component.html

    <div *ngIf="currentUser$ | async as currentUser">
                <a href="https://localhost:7298/api/auth" *ngIf="!currentUser.isAuthenticated">
                    <button class="bg-white text-cyan-500 px-4 py-2 rounded-full">Login</button>
                </a>
                @if(currentUser.isAuthenticated) {
                <span>{{currentUser.name}}</span>
                <a href="https://localhost:7298/api/auth/logout">
                    <button class="bg-white text-cyan-500 px-4 py-2 rounded-full">Logout</button>
                </a>
                }
            </div>
    

    getSessionMock

    public getSessionMock() {
        this.user$.next(mockUser);
     }
    
    1 回复  |  直到 9 月前
        1
  •  3
  •   Naren Murali    9 月前

    你必须返回可观察对象,而不是订阅它,你也可以使用 tap 以在流内产生副作用。

    只有这样 user$ 将在应用程序加载之前初始化。

     public user$ = new BehaviorSubject<AuthUser | null>(null);
    
      constructor(private readonly http: HttpClient) {}
    
      public getSession() {
        return this.http
          .get<SessionUser>('https://localhost:7298/api/auth/session', {
            withCredentials: true,
          })
          .pipe(
            tap((user) => {
              (user as AuthUser).isAuthenticated = true;
              this.user$.next(user as AuthUser);
            })
          );
      }
    

    你为什么打电话来 getSessionMock 不应该吗 getSession .

    export const appConfig: ApplicationConfig = {
    providers: [
        provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes),
        provideHttpClient(),
        provideAnimationsAsync(),
        {
          provide: APP_INITIALIZER,
          useFactory: (userService: UserService) => {
            return () => userService.getSession();
          },
          deps: [UserService],
          multi: true,
        },
      ],
    };