代码之家  ›  专栏  ›  技术社区  ›  Gargoyle

5等待多个子通知

  •  0
  • Gargoyle  · 技术社区  · 6 年前

    我有一个包含两个子组件的父组件。每个子级都有自己的网络负载,我需要在父级组件中知道两个子级何时完成了网络负载。我本以为我可以使用一个可观察的,但它不适合我。在我的两个子组件中,我都做到了:

    private _loadFinished = new BehaviorSubject<boolean>(null);
    loadFinished = this._loadFinished.asObservable();
    
    networkLoad() {
       this.network.doLoad().subscribe(x => {
           this._loadFinished.next(true);
       });
    }
    

    在父级的HTML中,我标记了每个子组件,然后在代码中这样做:

    @ViewChild('orgMetrics') orgMetrics: ChildComponentOne;
    @ViewChild('campusMetrics') campusMetrics: ChildComponentTwo;
    
    loading = true;
    
    ngOnInit(): void {
        forkJoin(
            this.orgMetrics.loadFinished,
            this.campusMetrics.loadFinished
        ).subscribe(() => {
            console.info("I got here");
            this.loading = false;
        }, () => this.loading = false);
    }
    

    这个 subscribe 永远不会被击中。我是不是走错方向了?我还看着她 EventEmitter

    3 回复  |  直到 6 年前
        1
  •  2
  •   Myk Willis    6 年前

    这个 forkJoin 函数将只在给定的可观测值 . i、 例如,当你简单地给出可观察物时,它不会发射

    因为你正在使用 BehaviorSubject this._loadFinished.next(true) 只会从可观察到的对象中发出一个值,它不会完成。

    一个简单的解决方法就是打电话 _loadFinished.complete() 发出唯一值后:

    networkLoad() {
       this.network.doLoad().subscribe(x => {
           this._loadFinished.next(true);
           this._loadFinished.complete();
       });
    }
    

    如果你有一些理由把行为主体放在身边,你可能也会发现 Observable.combineLatest

        2
  •  1
  •   Suresh Kumar Ariya    6 年前

    您正在访问ngOnInit()中的“@ViewChild('orgMetrics')”组件。但是正确的方法是使用ngAfterViewInit()。另一种方法是,在服务内部声明行为主体Observable和observator,并通过组件进行访问。

    服务:

    private _loadFinished = new BehaviorSubject<boolean>(null);
    loadFinished = this._loadFinished.asObservable();
    private _loadFinished1 = new BehaviorSubject<boolean>(null);
    loadFinished1 = this._loadFinished1.asObservable();
    
    load1Finished(){ //call this method from child component
      this.loadFinished.next(true);
    }
    
    load2Finished(){ //call this method from child component
      this.loadFinished1.next(true);
    }
    

    loading = true;
    
    ngOnInit(): void {
        forkJoin(
            this.Service.loadFinished,
            this.Service.loadFinished1
        ).subscribe(() => {
            console.info("I got here");
            this.loading = false;
        }, () => this.loading = false);
    }
    
        3
  •  0
  •   ferhado    6 年前

    你可以用 EventEmitter

    import { Component } from '@angular/core';
    @Component({
      selector: 'app-parent',
      templateUrl: './parent.html'
    })
    export class ParentComponent {
      onChanges(event){
        console.log(event);
      }
    }
    

    <app-child (valueChange)="onChanges($event)"></app-child>
    

    孩子:

    import { Component, EventEmitter } from '@angular/core';
    @Component({
      selector: 'app-child',
      templateUrl: './child.html'
    })
    export class ChildComponent {
      @Output() valueChange = new EventEmitter();
    
      networkFinished() {
        this.valueChange.emit('child1');
      }
    }
    

    Here is a working example