【问题标题】:Loop array of IDs and fetch data by Observable循环 ID 数组并通过 Observable 获取数据
【发布时间】:2021-07-17 12:48:57
【问题描述】:

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

获取数据基本上是一个返回 Observable 的数据库请求(对 Firestore)。通过使用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>

感谢您的帮助!

【问题讨论】:

    标签: arrays angular rxjs observable


    【解决方案1】:

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

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

    请注意:您不必订阅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$ 是一个 observables 数组,我们需要遍历各个 observables 并对每个 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>
    

    【讨论】:

    • 谢谢,我应用了你的方法,但我想我遗漏了一些东西。我的浏览器控制台给了我以下错误“错误错误:InvalidPipeArgument:'[object Object],[object Object]' for pipe 'AsyncPipe'”。此外,如果我尝试调试它并在我的 .ts 和 console.log 结果中订阅 devices$,它会以两行而不是数组显示数据。你知道为什么会这样吗?
    • 如果我 console.log(this.devices$): "(2) [Observable, Observable]" 这将显示我的控制台。我无法在我的 HTML 中使用异步管道,请参阅我之前的评论。我想有什么东西不见了?提前谢谢你。
    • 你是对的。这将返回一个可观察的数组。并且异步管道仅适用于单个 observable 或 observable of an array(使用 ngFor)。我们这里有一个array of observables。在这种情况下,我们必须首先遍历 devices$,并且对于每个设备,我们都需要一个异步管道。更新答案。请检查它是否有效。
    【解决方案2】:

    使用forkJoin,您可以等待所有可观察到complete。或者,您可以使用combineLatest,它会在每次一个可观察对象发出数据时为您提供最新的数据组合。这将导致更多事件,但不会等待全部完成。

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

    【讨论】:

      猜你喜欢
      • 2019-08-26
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      • 1970-01-01
      • 2016-03-23
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多