【问题标题】:Angular Service Observable doesnt trigger components subscription second timeAngular Service Observable 不会第二次触发组件订阅
【发布时间】:2018-10-03 12:04:48
【问题描述】:

我正在尝试将组件订阅到服务主题,以确保组件订阅在服务发射时运行。

问题是订阅只有第一次命中,之后订阅也没有命中第二次附加的可观察返回 0 订阅。

以下是代码:

export class StoreService {
    private storesList : Subject<Array<KeyValue<string>>> = null;

    constructor(private http: Http, private _uService: UserService) {
        this.storesList = new Subject<Array<KeyValue<string>>>();
     }
    loadStores(): void{
        this.getAllStores().subscribe(m=>{
            debugger;
            this.storesList.next(m);
        });
    }
    storeListEvent(): Observable<Array<KeyValue<string>>>{
    return this.storesList.asObservable();
    } 
}

当组件存在时。

export class HeaderNavComponent implements OnInit, AfterViewInit,OnDestroy  {

    private storeUpdateSubscription = null;    
    constructor(private _userService: UserService, private cdRef: ChangeDetectorRef, private _storeService: StoreService, private router: Router, private location: Location) {

        this.storeUpdateSubscription = this._storeService.storeListEvent().subscribe(stores => {
            debugger;
            this.appStore = stores;
            this.verifySuperAdmin();
        });
    }

旨在每次都在组件中调用上述订阅

调用 Store Service - loadStores 时

【问题讨论】:

  • 考虑使用new ReplaySubject&lt;Array&lt;KeyValue&lt;string&gt;&gt;&gt;(1) 保留最后一个值,直到loadStores() 提供next 值。这样,新订阅者将始终获得价值。
  • 你不会在任何地方破坏组件和服务吧?
  • 你能在stackbiz提供代码吗
  • @PranayRana 是的,我也没有破坏组件和服务。组件位于应用程序的 Header 部分,它会一直留在那里。
  • 你在哪里打电话给loadStores?

标签: angular typescript rxjs observable


【解决方案1】:

您的代码不完整(例如,没有getAllStores() 或storeListEvent() 方法,不清楚userService 做了什么)所以我要说的在您的情况下可能不正确。

无论如何,我建议你按照这些思路简化你的逻辑

  1. 从 StoreService 中删除主题
  2. 让loadStores() 方法返回一个 Observable
  3. 在 HeaderNavComponent 订阅 Observable 返回的 loadStores()
  4. 将订阅逻辑放在ngOnInit() 方法中,而不是 在构造函数中

这就是代码的样子

    export class StoreService {

        constructor(private http: Http, private _uService: UserService) {
         }
        loadStores(): Observable<Array<KeyValue<string>>> {
               return this.getAllStores();
        }
    }



    export class HeaderNavComponent implements OnInit, AfterViewInit,OnDestroy  {

        private storeUpdateSubscription = null;    
        constructor(private _userService: UserService, private cdRef: ChangeDetectorRef, private _storeService: StoreService, private router: Router, private location: Location) {}


      ngOnInit() {
            this.storeUpdateSubscription = this._storeService.subscribe(stores => {
                debugger;
                this.appStore = stores;
                this.verifySuperAdmin();
            });
        }
}

补充意见

我假设StoreService 的方法getAllStores() 通过您在构造函数中定义的Http 服务执行http 调用

查看你的代码getAllStores()返回一个Observable,否则你将无法subscribe

如果这是正确的,而不是订阅 getAllStores() 返回的 Observable 只是为了使用 HeaderNavComponent 订阅的另一个 Observable (storesList) 发出一个新值,您可以简单地让 HeaderNavComponent 订阅返回的 Observable通过getAllStores()方法

我希望现在更清楚了

【讨论】:

  • 我已经用 storeListEvent() 函数更新了代码,我想在每次调用 load Store of service 时运行组件的订阅。我对this._storeService.subscribe 感到困惑,你能解释一下吗
  • 我用更多的 cmets 编辑了我的回复。我希望这现在更清楚,它会有所帮助
  • 据我所知HeaderNavComponent subscribe to the Observable returned by getAllStores() method - 你的意思是在可观察的组件中使用订阅,每次我从其他组件调用getAllStores 时它的订阅都会命中。因为我想用每次任何组件调用该服务时更新的列表来更新标题组件。
  • 没有。如果有更多组件触发loadAllStores() 方法,并且您希望在loadAllStores() 方法执行时随时更新HeaderNavComponent,那么您的代码应该可以工作。你确定你没有在第一次和后续调用之间取消订阅storeUpdateSubscription吗?
  • 不,我不会在任何地方取消订阅它,它第一次工作,第二次当我看到主题订阅者时 - 它显示空订阅。
【解决方案2】:

我在这里要做的第一件事是调用this.storeList.next(m);,而不是在另一个订阅中,而是直接从你的函数中调用。如果可行,那么您就知道问题出在您的其他订阅上,而不是storesList。

【讨论】:

  • 实际上当this.storesList.next(m);第二次点击时,它总是得到空的订阅者——因为第一次调用下一次它有一个订阅者
【解决方案3】:

您正在应用反模式:切勿在同一服务中订阅服务调用。你必须返回调用并且组件必须订阅这个 Observable。

无论如何,由于 storeList 是一个主题,您可以简化操作:

this.getAllStores().subscribe(this.storesList);

因为主体也是观察者

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 2022-07-11
    • 2018-07-27
    相关资源
    最近更新 更多