【问题标题】:Angular BehaviorSubject isn't getting data from http callAngular BehaviorSubject 没有从 http 调用中获取数据
【发布时间】:2020-08-07 17:39:12
【问题描述】:

我正在尝试使用 behaviorSubject 以通过 http 调用从 db 获取用户名。当用户登录时,该进程应该被初始化。然后,当用户名发生更改时,我想显示它而不重新加载我的页面以获取更新的值。我对 BehaviorSubject 的概念和使用不熟悉,所以这就是我目前所拥有的。我创建了一个 Authservice,它从 Auth0Service 获取 isAuthenticated$(boolean) observable(我使用 auth0 进行身份验证)并检查用户是否已登录。当用户登录时,它会触发我的 getLoggedInUser 函数,该函数包含获取 http 调用的数据。但是当我想在 sidenav 中显示名称时,它是 null 女巫是 behaviorSubject 的初始值。所以我想我从来没有打电话来获取数据。

授权服务:

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  constructor(private api: ApiService, private auth0Service: Auth0Service ) { 
    this.auth0Service.isAuthenticated$.pipe(tap(isAuth => {
      if (isAuth) {
       this.getLoggedInUser()
        console.log(isAuth)
      }
    }));


   }

  private userSubject$ = new BehaviorSubject<any>(null);
  user$ = this.userSubject$.asObservable();

  getLoggedInUser(): Observable<any> {
    return this.api.getCurrentLoggedInUser().pipe(tap(user=> this.userSubject$.next(user)));

  }


}

sidenav 我调用 user$:

export class SidenavComponent implements OnInit {
 constructor(private authService: AuthService) {}

 getUser$ : Observable<User>;
 ngOnInit(): void {

    this.getUser$ =  this.authService.user$

 }

我第一次初始化的应用组件

export class AppComponent implements OnInit {
 constructor(public auth0Service: Auth0Service, private authService: AuthService) {}
 ngOnInit(): void {
    this.authService.user$;
 }
}

sidenav html:

   <div *ngIf="getUser$  | async as profile">
          <h3>{{profile.name}}</h3>
   </div>

谁能帮我理解为什么我没有得到任何数据?

更新:

我已经设法验证我最初什至没有进入 getLoggedInUSer 函数,但现在我将 this.getLoggedInUser() 调用移至我的 authguard,现在我可以成功地将 loggin boolean 记录为我的 getLoggedInUser( )。我现在尝试在 api 调用之后在 getLoggedInUser() 中记录 userSubject$,并在调用之前删除了 return。我在控制台中得到了这个:

BehaviorSubject {_isScalar: false, observers: Array(0), closed: false, isStopped: false, hasError: false, …}
value: (...)
_isScalar: false
observers: [Subscriber]
closed: false
isStopped: false
hasError: false
thrownError: null
_value: null
__proto__: Subject

空女巫似乎很奇怪,因为我在调用 api 后记录了这个

【问题讨论】:

  • 您能创建一个 stackblitz 示例吗?
  • 当你在 AuthService 中 console.log 用户时,输出是什么
  • Observable {_isScalar: false, source: BehaviorSubject} _isScalar: false source: BehaviorSubject value: (...) _isScalar: false observers: [Subscriber] closed: false isStopped: false hasError: false thrownError: null _value: null __proto__: Subject __proto__: Object
  • 如果我在 sidenav 中订阅它并记录它,则日志为空
  • @StepUp 我以前从未使用过 stackblitz,我不确定是否可以在不使用 http 调用的情况下成功创建一个工作示例?

标签: angular http next behaviorsubject


【解决方案1】:

您的服务不应调用构造函数this.auth0Service.isAuthenticated$. 中的方法。这些方法应该分开:

import { HttpClient } from '@angular/common/http';
import {Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';


@Injectable({
  providedIn: 'root'
})
export class AuthService {
    constructor(private api: ApiService, 
        private auth0Service: Auth0Service ) {}


    this.auth0Service.isAuthenticated$
        .pipe(map(v => v));


    getLoggedInUser(): Observable<any> {
        return this.api.getCurrentLoggedInUser()
            .pipe(map(v => v));
    }
}

并且您的组件可以使用asyncawait 关键字从上述服务中获取数据。

your.component.ts

user: any;
async ngOnInit() {
    let isAuthenticated = this.authService.isAuthenticated.toPromise();
    if (isAuthenticated) {
        this.user = this.authService.getLoggedInUser().toPromise();          
        console.log(this.user);
    }
}

HTML:

<div *ngIf="user">
     <h3>{{user | json}}</h3>
</div>

更新:

您可以使用Observable 获取最近更新的用户:

user: any;  

ngOnInit() {
    this.authService.isAuthenticated.pipe(
        tap(val => console.log(val)),
        switchMap(val => this.authService.getLoggedInUser())
        ).subscribe(user => {
            this.user = user;
        });
}

【讨论】:

  • 您好,感谢您的回答,我忘了提供我的 html,但我确实使用了 | html 中的异步。我会将我的 html 添加到我的问题中,以免进一步混淆。
  • 如果我在组件中登录用户,我尝试了你的答案我可以看到用户数据,但只有我的 user$ | async as profile --&gt; &lt;p&gt;{{profile.name}} &lt;/p&gt; 没有显示用户名,但我确实在我的控制台中得到了它
  • 您好,感谢您帮助它以这种方式工作!但我仍在寻找它与我在问题中尝试做的 behaviorSubject 一起工作
  • @imkeVr 为什么要使用behaviourSubject
  • 因为我想将它与asObservable.next() 结合使用(正如我在我的问题中试图做的那样)以获得连续的数据流。这意味着当用户更改他的用户名时,应用程序不应重新加载,以便用户在侧边栏中看到他更新的用户名。因此,如果数据发生变化,我希望始终显示最新值而不重新加载应用程序
猜你喜欢
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 2021-07-10
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
相关资源
最近更新 更多