循环 ID 数组并通过 Observable 获取数据

Loop array of IDs and fetch data by Observable

我有一个 device_ids 的数组。通过选择 UI 上的项目动态扩展数组。 最初以及每当更新数组时,我都需要遍历它并为每个 device_id 获取数据。 G

获取数据基本上是一个数据库请求(到 Firestore),returns 一个 Observable。通过使用 switchMap 我从其他数据库请求中获取了一些数据。

最后我想要一个类似对象/Observables 的数组,其中包含我可以订阅的所有数据。我的目标是在我的 HTML 中使用 Angular 的异步管道。

这可能吗(例如使用 RxJS)?我不确定如何解决这个问题...

这是我的代码目前的样子:

// Init
devices$: Observable<any;

// Array of device_ids
device_ids = ['a', 'b'];

// Get device data. This will initially be called on page load.
getDeviceItemData(device_ids) {

    // Map / loop device_ids
    device_items.map(device_id => {

        // getDeviceById() returns an Observable
        return this.getDeviceById(device_id).pipe(

        // Switch to request additional information like place and test_standard data
        switchMap(device => {

            const place$ = this.getPlaceById(device['place_id]');
            const test_standard$ = this.getTestStandardById(device['test_standard_id]');

            // Request all data at the same time and combine results via pipe()
            return zip(place$, test_standard$)
                .pipe(map(([place, test_standard]) => ({ device, place, test_standard })));
        })
        ).subscribe(device_data => {
            // Do I need to subscribe here?
            // How to push device_data to my Observable devices$?
            // Is using an Observable the right thing?
        });
    });
}

// Add device
addDevice(device_id) {

    // Add device_id to array
    this.device_ids.push(device_id);

    // Fetch data for changed device_ids array
    getDeviceItemData(this.device_ids);
}

使用异步管道的首选 HTML / Angular 代码:

<div *ngFor="device of devices$ | async">{{ device.name }}</div>

感谢您的帮助!

使用 rxjs 绝对可以做到这一点。你走在正确的道路上。我对您的 getDeviceItemData() 方法做了一个小修改。

一旦通过 id 检索到设备信息,您就可以使用 forkJoin 并行执行两个调用以获取 place 和 test_standard 数据,然后将该数据映射到 return 您需要的对象,其中包含设备信息、地点信息和 test_standard 作为可观察对象。由于我们映射到 device_ids,它会生成一个包含所需对象的可观察对象数组,以便您可以轻松地将它们与异步管道结合起来。

请注意:您不必订阅 devices$,因为 async pipe 会自动为您订阅。

请看下面的代码:

  // Init
  devices$: Observable<{ device: any, place: any, test_standard: any }>[];

  // Array of device_ids
  device_ids = ['a', 'b'];

  getDeviceId: (x) => Observable<any>;
  getPlaceById: (x) => Observable<any>;
  getTestStandardById: (x) => Observable<any>;

  getDeviceItemData() {
    this.devices$ = this.device_ids.map((id) =>
      this.getDeviceId(id).pipe(
        switchMap((device) => {
          return forkJoin([
            this.getPlaceById(device['place_id']),
            this.getTestStandardById(device['test_standard_id'])
          ]).pipe(map((y) => ({ device, place: y[0], test_standard: y[1] })));
        })
      )
    );
  }

在您的 HTML 中,您必须执行以下操作:

编辑:由于 devices$ 是一个 observable 数组,我们需要迭代各个 observable 并对每个 observable 应用异步管道。

<div *ngFor="device of devices$">
  <div *ngIf="device | async as device"> 
    <div>{{ device.device.name }}</div>
    <div>{{ device.place}}</div>
    <div>{{ device.test_standard }}</div>
  </div>
</div>

使用 forkJoin,您可以等待所有可观察到 complete。或者你可以使用 combineLatest ,它会给你最新的数据组合,每次一个 observable 发出数据。这将导致更多事件,但不会等待所有事件完成。

getDeviceItemData(device_ids) {
  const arrayOfObservables = device_ids.map(device_id => {
    return this.getDeviceById(device_id).pipe(...);
  }
  return combineLatest(arrayOfObservables); // Observable<Data[]>
}