首页 > 解决方案 > 获取和存储全局变量

问题描述

我正在为一个简单的概念而苦苦挣扎,我可以在 C# 中轻松完成,但在 Angular 中却不行。

我正在尝试将用户配置文件存储在我在每个组件中添加的服务中,因此每次加载/显示组件时我都不会获取配置文件。

因此,我创建了一个服务,构造函数在其中获取用户配置文件,并将其保存在一个变量中,并对我的所有组件使用 getter。

我遇到的问题是,当组件调用 getter 时,变量已设置为 net,因为服务尚未响应。这会导致未定义的错误并破坏组件,因为配置文件在组件的代码中至关重要。

在 C# 中,我会在获取配置文件时简单地放置 1 await,以便其他一切都可以运行而无需等待,因为我知道数据就在那里。

但是在 Angular 中,我尝试过,但它似乎不起作用。

export class SharedService {
  private userProfile;
  constructor(private http: HttpService) {
    this.initProfile();
  }
  async initProfile(): Promise < void > {   
    this.userProfile =await this.http.getProfile().subscribe((data: any) => {
       //...
    }
  });

  getUserProfile() {
    return this.userProfile;
  }
} 

获取配置文件:

  getProfile() {
    return this.shttp.get(environment.apiEndpoint + 'Getprofile/', {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        Accept: '*/*'
      })
    });
  }

在组件中,当我调用 getUserProfile 函数时,服务会立即使用空的 userProfile 进行响应。

编辑:我设法通过非常讨厌的代码片段获得所需的行为,但这应该清楚我想要完成的事情。在我的 profile.component.ts 中:

async ngOnInit(): Promise<void>  {    
 while (this.profile == null) {
  await this.sharedService.sleep(500);
  this.profile = this.sharedService.getUserProfile();    
 }
 if (this.profile.isadmin){
  this.CalculateStuff();
 }
 //
 //imagine here even more code using the this.profile variable in if statements, 
 //cases, etc.
 //
}

睡眠功能

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

我必须编写一个睡眠函数来实现这一点,这对我来说是一个明确的信号,表明我做错了。这就是我在这里的原因。

标签: angular

解决方案


另一种方法是使服务中的多播可观察(如带有缓冲区 1userProfile的 RxJS )。ReplaySubject这样就不需要将 observables 与 Promise 混合在一起。

服务

import { ReplaySubject } from 'rxjs';

export class SharedService {
  private userProfile = new ReplaySubject<any>(1);

  constructor(private http: HttpService) {
    this.initProfile();
  }

  initProfile() {   
    this.http.getProfile().subscribe({
      next: (data: any) => {
        this.userProfile.next(data);           // <-- push the new profile
      },
      error: (error: any) => { }               // <-- handle error
  });

  getUserProfile(): Observable<any> {          // <-- return observable here
    return this.userProfile.asObservable();
  }
}

现在在组件中,您可以从服务订阅主题。此外,当组件关闭/销毁时,您可以使用takeUntiloperator with来关闭打开的订阅。Subject

零件

import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class SomeComponent implements OnInit, OnDestroy {
  public userProfile: any;
  private closed$ = new Subject<any>();

  constructor(private shared: SharedService) { }

  ngOnInit() {
    this.shared.getUserProfile().pipe(
      takeUntil(this.closed$)
    ).subscribe({
      next: (data: any) => {
        this.userProfile = data;
        // other statements that depend on `this.userProfile`
      }
    });
  }

  ngOnDestroy() {
    this.closed$.next();   // <-- close open subscription(s)
  }
}

推荐阅读