在BehaviourSubject中获得未定义的订阅

时间:2020-07-31 07:04:42

标签: angular rxjs

我正在尝试订阅由父组件设置的BehaviourSubject并将其放入子组件中,我试图在我的组件中添加以下内容:

export class ModuliComponent implements OnInit {
  public profilo: Profilo;

  constructor(public profiloService: ProfiloService) { }

  ngOnInit(): void {
    this.profiloService.dataProfilo.subscribe(data => this.profilo = data); // setting profilo
  }

}

但是当我尝试在HTML中使用profilo时,我只是在undefined或其他* ngIf

上获得了asporto

enter image description here

我做错了什么?我应该首先初始化profilo吗?即使是这样,即使设置onInit或在constructor中,profilo = new Profilo();也会得到未定义的错误...

如果我将console.log设置为订阅,它将返回正确的数据,因此asporto和订阅中的其他内容并不是未定义的。

此处要求提供ProfiloService

@Injectable({
  providedIn: 'root'
})
export class ProfiloService {

  public dataProfilo = new BehaviorSubject<any>([]);

  constructor(private http: HttpClient, private adapter: ProfiloAdapter) { }

  profilo(idNegozio: string): Observable<Profilo>{
    return this.http
    .get(`${Globals.API_URL}/profilo/${idNegozio}`)
    .pipe(map((data: any) => this.adapter.adapt(data)));
  }
}

这是我要设置dataProfilo的组件:

this.profiloService.dataProfilo.next(profilo);

控制台。从订阅数据登录

enter image description here

编辑:

如果我在父div *ngIf="profilo.moduli"上添加它可以正常工作,但是此时profilo是未定义的,为什么为什么做一个简单的 *ngIf="profilo"还不够?

3 个答案:

答案 0 :(得分:1)

在html中使用?运算符

<div *ngIf="profilo?.moduli?.ticketing" ></div>

答案 1 :(得分:1)

如果默认情况下将有一个空数组,并检查模板中是否未定义该数组,则建议您将ReplaySubject与缓冲区1结合使用。它类似于BehaviorSubject,但不需要默认值。

@Injectable({
  providedIn: 'root'
})
export class ProfiloService {
  public dataProfilo = new ReplaySubject<any>(1);

  constructor(private http: HttpClient, private adapter: ProfiloAdapter) { }

  profilo(idNegozio: string): Observable<Profilo>{
    return this.http
    .get(`${Globals.API_URL}/profilo/${idNegozio}`)
    .pipe(map((data: any) => this.adapter.adapt(data)));
  }
}

此外,如果仅在控制器中预订可观察对象以仅在模板中直接使用它,则最好使用async管道。至少,它可以解决退订问题。

子组件

export class ModuliComponent implements OnInit {
  public profilo$: Observable<any>;

  constructor(public profiloService: ProfiloService) { }

  ngOnInit(): void {
    this.profilo$ = this.profiloService.dataProfilo;
  }

}

模板

<ng-container *ngIf="(profilo$ | async) as profilo">
  <section>
    ...
  </section>
</ng-container>

<section>标记内的模板不必更改,因为我们使用*ngIf指令的as签名来表示可观察对象的当前值。

答案 2 :(得分:0)

当初始化子组件时,profilo var是未定义的,并且当API返回数据时,profilo var仅具有数据。因此,您可以使用“?”操作员,或按如下所示检查profilo变量。

<div *ngIf="profilo?.moduli?.ticketing" ></div>

OR

<div *ngIf="profile && profile.moduli && profile.profile.ticketing" ></div>