如何处理未定义的 Observable

Posted

技术标签:

【中文标题】如何处理未定义的 Observable【英文标题】:How to handle undefined Observables 【发布时间】:2021-06-03 03:25:48 【问题描述】:

在我的 Angular 服务中,我提供了一个名为 usageDoc$ 的公共 Observable。

service.ts:

usageDoc$: Observable<IUsage>;

initializeUsageDoc() 
  //gets called in app.component.ts on app load
  ...
  //some async db querying

  this.usageDoc$ = this.firestore.getUsageDoc(user.uid);  //getUsageDoc(..) returns Observable<IUsage>

组件.ts

localDoc: any;

ngOnInit() 
  this.service.usageDoc$.subscribe(doc=>this.localDoc=doc);

这会导致以下错误:cannot read property subscribe of undefined... as usageDoc$ is not yet set on the component init.目前我正在使用一种解决方法,即在服务中创建第二个可观察的usageDocReady$ = new Subject&lt;boolean&gt;,一旦设置usageDoc$,就会发出。

有没有更好的方法来解决这个问题?我可以用默认值以某种方式初始化 usageDoc$ 吗?

我知道如果我使用异步管道在模板中订阅我不会有这个问题,但我需要一个普通变量来显示问题,因此使用localDoc

【问题讨论】:

【参考方案1】:

我建议使用带有缓冲区 1 的 ReplaySubject。它可以确保未来的订阅者获得最后一次发射,同时避免任何 undefined 错误。

private usageDocSrc = new ReplaySubject<IUsage>(1);
public usageDoc$ = this.usageDocSrc.asObservable();

initializeUsageDoc() 
  //gets called in app.component.ts on app load
  ...
  //some async db querying

  this.firestore.getUsageDoc(user.uid).subscribe(
    next: value => this.usageDocSrc.next(value)
  );

如果您不想使用ReplaySubject,那么我不明白需要Observable。您可以直接从 getUsageDoc() 函数返回 observable。

initializeUsageDoc(): Observable<IUsage> 
  //gets called in app.component.ts on app load
  ...
  //some async db querying

  return this.firestore.getUsageDoc(user.uid);

尽管这会为每次订阅initializeUsageDoc() 调用getUsageDoc() 之前的所有语句。

【讨论】:

拥有usageDoc$usageDocSrc 有什么意义? @BojanKogoj:这是一种习惯力量,使用来自 SubjectReplaySubject 等多播的 asObservable() 构造。有些人宁愿不使用它:usageDoc$ = new ReplaySubject&lt;IUsage&gt;(1)。另请参阅here。 如果您试图阻止任何人从外部服务中获取下一步,那么这是有道理的。在这种情况下,也将 usageDocSrc 设为私有? @BojanKogoj:是的,这是惯例(或者至少以前是这样)。我已经更新了答案。

以上是关于如何处理未定义的 Observable的主要内容,如果未能解决你的问题,请参考以下文章

等待/异步如何处理未解决的承诺

swift - 如何处理未捕获的异常

如何处理未提交的更改

如何处理未打开的推送通知(iOS、Swift)

如何处理未捕获(承诺)DOMException:播放()请求被暂停()调用中断

如何处理未捕获的错误:对象作为 React 子错误无效