【问题标题】:What's the proper pattern to wait on an observable? [duplicate]等待 observable 的正确模式是什么? [复制]
【发布时间】:2019-08-22 13:51:01
【问题描述】:

我有两种服务:一种依赖于另一种。服务 A 进行 http 调用以获取数据。服务 B 实际使用该数据。

服务 A:

@Injectable({
  providedIn: 'root'
})
export class ServiceA {
  data: MyData;

  getData(): Observable<MyData> {
    return this.http.get<Mydata>('http://some.url')
      .pipe(
        tap((data: MyData) => {console.log(`got data');})
      )
    );
  };
}

服务 B:

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

  obs = Observable<MyData> = new Observable<MyData>();
  processedData: string[];

  constructor(private serviceA: ServiceA) {
    this.obs = this.serviceA.getData();
    this.obs.subscribe( 
      data => {this.processedData = process(data)},
      error => { /*process error*/ },
      function() { /* maybe mark flag here? */}
      );
  }

  process(endpointData) {
     // Do some business logic to endpointData
     this.processedData = endpointData;
  }

  processedData() {
    // The first time this is called, the observable hasn't completed
  }
}

服务 B 的客户端将调用 processesData()。只是好奇如何优雅地等待 processData() 中的 observable。我的非异步方面想检查 observable 的 finally 部分是否已被调用。如果是这样,只需使用 this.processedData。如果不是……那又怎样?我想我可以订阅一次,在处理数据中,并且只在第一次调用时。这似乎仍然不太正确。想法?

【问题讨论】:

  • 您是否尝试过使用 toPromise() 将 observable 转换为可以等待的单个调用?
  • 这可能会有所帮助。 stackoverflow.com/questions/44593900/…
  • @chrismclarke 我确实考虑过 toPromise() 但我读过的大多数地方都建议不要将其用作对问题的全面回应。

标签: angular rxjs observable


【解决方案1】:

等待Observable的正确方法不是等待,而是聆听

constructor(private readonly serviceA: ServiceA) {
  this.data$ = this.serviceA.getData().pipe(
     map(data => process(data)),
     shareReplay(1)
  );

  // Immediately subscribe to execute the HTTP call
  this.data$.subscribe({
    error: error => { /* Process error */ },
  });
}

...

processedData(): Observable<MyData> {
  // Return the data "holder".
  // The result will already be there, or in the process of being retrieved
  return this.data$;
}

使用 pipable 运算符 shareReplay 意味着 Observable 充当 缓存,在每个后续订阅中返回 最新计算值 .

serviceB.processedData().subscribe({
  next: data => ...
})

数据可以立即可用,或者需要一些时间来计算。

【讨论】:

  • 谢谢,这看起来像我想要的。我正要编辑帖子并说,“我是否应该向调用者返回一个 observable”,这看起来是肯定的,但需要做一些额外的工作。
  • @kiss-o-matic 这没什么。事实上起源(HTTP 调用)是一个异步操作。一旦你开始一个异步操作,就很难逃脱这个链条。我建议接受 Angular 的异步特性。
  • @kiss-o-matic 额外的跑腿工作我什至不会考虑,它真的很小,它可以避免程序编程的所有问题。
  • @kiss-o-matic 开始时没问题。我们都在那个时候。多读书吧。
  • @kiss-o-matic 我将把map 移到constructor 中。已更新。
猜你喜欢
  • 1970-01-01
  • 2020-09-10
  • 2014-05-08
  • 2022-10-15
  • 2013-01-09
  • 2016-05-10
  • 2014-12-28
  • 1970-01-01
  • 2014-05-04
相关资源
最近更新 更多