循环 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[]>
}
我有一个 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[]>
}