首页 > 解决方案 > 结合最新和返回值

问题描述

在第一个示例中,我有一个调用此 ClientService 的组件。首先我们调用 loadClientMetrics 来填充属性,然后获取属性并立即将它们发送到 calculateClientInsightsMetrics 函数中。但是,我想像第二个示例中那样更改服务以利用服务中的属性,而不必将它们拉出来只是为了将它们传回。下面是我想做的,但是 combineLatest 之前没有返回返回值,并返回 undefined。有人可以帮我吗?我正在寻找一种在返回值返回之前让 combineLatest 完成的方法。

主要问题是我有一个进行异步调用的同步方法。

  export class ClientService {

  private metrics = new BehaviorSubject<ClientMetrics>(undefined);
  public metrics$ = this.metrics.asObservable().pipe(distinctUntilChanged(), shareReplay(1));
  private clients = new BehaviorSubject<Client[]>(undefined);
  public clients$ = this.clients.asObservable().pipe(distinctUntilChanged(), shareReplay(1));
  private clientsBySHID = new BehaviorSubject<Client[]>(undefined);
  public clientsBySHID$ = this.clientsBySHID.asObservable().pipe(distinctUntilChanged(), shareReplay(1));
  
  ...
  
  public loadClientMetrics(forceReload: boolean = false) {
    this.loadMetrics(forceReload);
    this.loadClients(forceReload);
    this.loadClientsByShareholderID(forceReload);
  }
  
  ...
  
  public calculateClientInsightsMetrics(metrics: ClientMetrics[], clients: Client[], kycClients: Client[], clientFilter: string): ClientInsightsMetric[] {
      
      let metrics = new Array<ClientInsightsMetric>();
      
    ...Do stuff
    
    return metrics;
      
  }

}
   export class ClientService {

  private metrics = new BehaviorSubject<ClientMetrics>(undefined);
  public metrics$ = this.metrics.asObservable().pipe(distinctUntilChanged(), shareReplay(1));
  private clients = new BehaviorSubject<Client[]>(undefined);
  public clients$ = this.clients.asObservable().pipe(distinctUntilChanged(), shareReplay(1));
  private clientsBySHID = new BehaviorSubject<Client[]>(undefined);
  public clientsBySHID$ = this.clientsBySHID.asObservable().pipe(distinctUntilChanged(), shareReplay(1));
  
  ...
  
  public loadClientMetrics(forceReload: boolean = false) {
    this.loadMetrics(forceReload);
    this.loadClients(forceReload);
    this.loadClientsByShareholderID(forceReload);
  }
  
  ...
  
  public calculateClientInsightsMetrics(clientFilter: string): ClientInsightsMetric[] {
      
      let metrics = new Array<ClientInsightsMetric>();
      this.loadClientMetrics(false);

      combineLatest([
      this.metrics$,
      this.clients$,
      this.clientsBySHID$
    ]).subscribe(data => {
        
      ...Do stuff with the data[0], data[1], and data[2]
      
    });
    
    return metrics;
      
  }

}

标签: angulartypescript

解决方案


看起来传递给subscribe( ) 的回调在' 执行data => { ....中没有同步执行。calculateClientInsightsMetrics它可能看起来像这样:

  1. 称呼calculateClientInsightsMetrics
  2. 调用combineLatest并将订阅者回调传递subscribe给返回的可观察对象。请注意,您的订阅者回调中定义的任何工作都尚未完成。
  3. 返回metrics(尚未分配给!)
  4. 某个非零时间之后,订阅事件发生并metrics在订阅者回调中分配(为时已晚)。

换句话说,您需要一种强制同步执行的方法(查看combineLatest的文档),或者您更有可能需要“承诺”您的订阅(注意这需要异步执行):

public async calculateClientInsightsMetrics(clientFilter: string): ClientInsightsMetric[] {
      
    let metrics = new Array<ClientInsightsMetric>();
    this.loadClientMetrics(false);

    metrics = await new Promise(resolve => combineLatest([
      this.metrics$,
      this.clients$,
      this.clientsBySHID$
    ])
    .subscribe(data => {
      // do what you need to do and call resolve(), passing the value for metrics
      resolve(data);
    }));

    return metrics;
}

请注意,这违背了订阅的全部目的:您将只能使用传递给订阅者回调的第一个/下一个值。


推荐阅读