【问题标题】:Why subscribe on BehaviourSubject asObservable never fires onComplete?为什么订阅 BehaviorSubject Observable 永远不会触发 onComplete?
【发布时间】:2018-10-26 11:10:24
【问题描述】:

我正在使用 Angular。我有用于存储和从本地存储中获取数据的服务。我将 BehaviorSubject 保存为 Observable()。 代码如下:

import { Injectable} from "@angular/core";
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class NavigationStorageService {

  ModuleTitle = new BehaviorSubject<string>("");
  currentModuleTitle = this.ModuleTitle.asObservable();

  constructor() {}

  setModuleId(ModuleId) {
    localStorage.setItem('subModuleId', ModuleId)
    this.ModuleTitle.next(ModuleId);   
  }

  getModuleId() {
    this.ModuleTitle.next(localStorage.getItem('subModuleId'));
    return this.currentModuleTitle;
  }
}

接下来我将使用以下代码获取这些数据:

getModuleId() {
  this._navigationStorageService.getModuleId()
    .subscribe(
      subModuleId => {
        this.subModuleId = subModuleId
      },
      error => {
        console.log(error)
      },
      () => console.log("getModuleId"));
}

我的问题是我想在 observable 完成时执行其他功能,但这个 observable 从未完成,所以我不能这样做。

() => console.log("getModuleId") 没有显示消息。

我该如何解决这个问题?

在我的应用程序的另一部分,我使用 Observable 来获取 HttpClient 请求,它工作正常。我的意思是 onComplete 会触发它。

我尝试过使用 .finally()

    getModuleId() {
    this._navigationStorageService.getModuleId()
        .finally(() => console.log("getModuleId"))
        .subscribe(
            subModuleId => {
                this.subModuleId = subModuleId
            },
            error => {
              console.log(error)
            },
            () => console.log("getModuleId"));
}

但没用。

【问题讨论】:

  • 我认为你必须手动调用完成,因为 observable 不知道它何时完成。请参阅rxjs 了解更多信息。否则,只需在订阅 observable 传递的值时调用您想要的函数,比如得到一个新值 -> 调用该函数。

标签: angular rxjs observable behaviorsubject


【解决方案1】:

只有当您通过调用 complete() 告诉他们完成时,主题才会完成。

这里的问题是您要达到的目标。您可能永远不希望主题完成,因此您永远不会调用this.ModuleTitle.complete(),但您仍想将complete 通知发送给currentModuleTitle 的“消费者”。

这意味着您可以使用take(1) 运算符,它只取一个值并立即完成链(无需使用asObservable)。

currentModuleTitle = this.ModuleTitle.take(1);

现在,每次您执行currentModuleTitle.subscribe() 时,您都会立即收到一个值并完成。请注意,BehaviorSubject 首先发出其存储的值,因此currentModuleTitle 的所有消费者实际上只会收到缓存的值,而不会进一步更新。

【讨论】:

  • 这正是我所需要的。谢谢。
【解决方案2】:

您正在使用错误的 Observable 对象。当您使用 getModuleId() 方法获取 localStorage 项目时,您会立即获得此值,然后 Observable 没有意义。

 import { Injectable} from "@angular/core";
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class NavigationStorageService {

  ModuleTitle = new BehaviorSubject<string>("");
  currentModuleTitle = this.ModuleTitle.asObservable();

  constructor() {}

  setModuleId(ModuleId) {
    localStorage.setItem('subModuleId', ModuleId)
  }

  getModuleId(id) {
    return localStorage.getItem(id);
  }
}

【讨论】:

    猜你喜欢
    • 2021-12-22
    • 2019-02-27
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 2018-08-03
    • 2022-07-11
    相关资源
    最近更新 更多