Rxjs 如何在智能组件中等待所有来自动态组件的观测值完成。

问题描述 投票:3回答:1

在我的项目中,我想通过点击页面上的一个按钮来导出(PDF)。在我的页面中,我有一个动态创建多个图表的仪表盘。当我点击 "export "按钮时,我想通知每个动态组件从当前的图表实例中创建一个svg,并将其传递给 "page "组件。为了能够创建一个svg,我必须等到一个图表实例被创建。当我从不同的动态组件中得到所有的svg时,我就可以将信息(不同的svg)传递到api调用的主体中,从而创建一个pdf。

所以我尝试在一个 测试项目. 我不知道正确的方法,所以我试着从服务中用动态组件中的观测值来填充一个数组,我的问题是如何知道所有动态组件中的观测值(失败时返回SVG或错误)都被添加到数组中,然后再在动态组件中做forkjoin。

我遇到的问题是,我如何知道所有来自动态组件的观测值(当它失败时,会返回SVG或错误)都被添加到数组中,然后才在 着陆页 组件。我的forkJoin也没有返回svg,所以我做错了什么。但也许有一个更好的方法,就是等待所有的动态组件,直到他们创建他们的svg's。

angular highcharts rxjs
1个回答
2
投票

我认为问题是,当 chartInstanceStream$ 发出,它没有订阅者,这意味着它无法完成,因 first()这也意味着 forkJoin 不会发射,除非所有提供的观测值至少发射一次并完成。

chartInstanceStream$ 发射的原因是 setChartInstance,这发生在 testService.clickExportPdfStream 发射。

一个快速的解决方案是将 chartInstanceStream 变成 ReplaySubject 以致于 重播 的最新值到 迟交者.

所以,从这个,

chartInstanceStream$ = new Subject<Highcharts.Chart>();

到这个

chartInstanceStream$ = new ReplaySubject<Highcharts.Chart>(1);

forkJoin 内部订阅了所有提供的观测值。通过将 chartInstanceStream$ 变成 ReplaySubject你要确保迟来的用户(那些来自中国的用户)。forkJoin)将接收到最古老的由 ReplaySubject.

而且因为你的可观察的东西 forkJoin 认购是这样的。

this.chartInstanceStream$.pipe(
    map((chart: Highcharts.Chart) =>
      chart.getSVG()
    ),
    first() // !
  )

在它们发出一个值后,它们会立即完成,由于... ... first().


0
投票

像你这样使用service的方法是一种方法。

另一种解决方案可能是导出一个 public 函数,然后从你的父组件中调用它们。

例如,我有这个简单的 ChartComponent 模仿svg导出。

@Component({
  selector: "app-chart",
  templateUrl: "./chart.component.html",
  styleUrls: ["./chart.component.css"]
})
export class ChartComponent {
  exportSvg(): Observable<string> {
    return defer(() => 
      timer(Math.random() * 2000 + 500).pipe(mapTo('svg'))
    )
  }
}

现在在我的父组件中,我查询这些组件并调用 exportSvg 的需求。

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  @ViewChildren(ChartComponent) charts: QueryList<ChartComponent>;

  onExportClick(): void {
    const charts = this.charts.map(component => component.exportSvg());

    forkJoin(charts).subscribe(console.log)
  }
}

在我的例子中,我没有创建 ChartComponent的动态,但它的行为应该是一样的。

完整的例子可以在 这场突击赛

© www.soinside.com 2019 - 2024. All rights reserved.