【问题标题】:Will overwriting my observable variable kill current subscribers?覆盖我的可观察变量会杀死当前订阅者吗?
【发布时间】:2019-03-02 17:30:54
【问题描述】:

我希望能够缓存 http 调用,但也强制缓存刷新。我的服务如下所示:

@Injectable()
export class UserService {
  private currentUser$: Observable<User>;

  constructor(private http: HttpClient) { }

  getCurrentUser(force = false): Observable<User> {
    if (!this.currentUser$ || force) {
      this.currentUser$ = this.http.get<User>(`${environment.API_URL}/profiles/me`)
        .pipe(
          shareReplay(CACHE_SIZE)
        );
    }
    return this.currentUser$;
  }
}

如果我调用getCurrentUser(true)currentUser$ 变量将被覆盖。恐怕这会消灭任何现有的订户。这是真的?我该如何保存它们?

【问题讨论】:

    标签: angular rxjs observable rxjs6


    【解决方案1】:

    this.currentUser$ 视为指向堆上的一个对象。 您的方法返回对this.currentUser$ 的引用的副本。所以所有订阅的观察者将继续监听它们(直到它们都取消订阅并且 Observable 被垃圾收集)。

    如果您使用“强制”调用该方法,this.currentUser$ 将仅指向堆上其他位置的另一个 Observable&lt;User&gt;

    【讨论】:

    • 那么你是说我在内存中有两个 Observable 吗?一个由变量指向,一个没有变量?您是否还说由于第一个 Observable 仍然有订阅者,它不会被垃圾收集?听起来像是内存泄漏。
    • 另外,第一个 Observable 的订阅者是否会不再收到更新,因为没有变量可以推送新值?
    • 这些是正确的结论:)。当然,如果你传递那个 Observable,其他一些对象可以推送新值。但我想情况并非如此。此外,您必须小心内存泄漏。始终取消订阅您的 Observables。有很多关于这个的问题/答案。
    • 我会接受您的回答,因为它确实回答了我的问题,但是您能否看看 my solution,如果您发现任何问题,请告诉我?
    • 我没有足够的积分来评论您的代码如下:)。但是看 rxjs .take(1) 收到东西后自动退订。
    【解决方案2】:

    我将在这里发布我所做的事情,以防它对其他人有所帮助。我改为返回BehaviorSubject 的单个实例,并在需要“强制”获取当前用户时向其推送新值。我还添加了一个标志fetchingCurrentUser,这样我就不会在等待对 API 的第一次调用完成时进行多次调用。

    如果有人对此有任何问题或对如何使其更干净有任何想法,请告诉我。谢谢。

    @Injectable()
    export class UserService {
      private currentUser$: BehaviorSubject<User>;
      private fetchingCurrentUser: boolean;
    
      constructor(private http: HttpClient) {
        this.currentUser$ = new BehaviorSubject(null);
      }
    
      getCurrentUser(force = false): Observable<User> {
        if (this.currentUser$.value == null || force) {
          this.refreshCurrentUser();
        }
        return this.currentUser$.asObservable();
      }
    
      refreshCurrentUser() {
        if (!this.fetchingCurrentUser) {
          this.fetchingCurrentUser = true;
          this.http.get<User>(`${environment.API_URL}/profiles/me`)
            .subscribe(x => {
              this.currentUser$.next(x);
              this.fetchingCurrentUser = false;
            });
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      • 2015-03-13
      • 2015-04-03
      • 1970-01-01
      • 2016-02-07
      • 1970-01-01
      • 2018-07-17
      相关资源
      最近更新 更多