如何用RxJS重构传统的同步循环?
我是RxJS的新手,我正试着思考应该如何编写代码。我试图编写一个函数来扩展现有的http,它返回一个可观察的数据数组。然后我想在数组上循环,对每个对象发出http请求,并返回带有修改数据的新数组 以下是我目前掌握的情况:如何用RxJS重构传统的同步循环?,rxjs,Rxjs,我是RxJS的新手,我正试着思考应该如何编写代码。我试图编写一个函数来扩展现有的http,它返回一个可观察的数据数组。然后我想在数组上循环,对每个对象发出http请求,并返回带有修改数据的新数组 以下是我目前掌握的情况: private mapEligibilitiesToBulk(bulkWarranties: Observable<any[]>): Observable<IDevice[]> { const warranties: IDevice[] = []
private mapEligibilitiesToBulk(bulkWarranties: Observable<any[]>): Observable<IDevice[]> {
const warranties: IDevice[] = [];
bulkWarranties.subscribe((bulk: any[]) => {
for (let warranty of bulk) {
// Check if another device already has the information
const foundIndex = warranties.findIndex((extended: IDevice) => {
try {
return warranty.device.stockKeepingId.equals(extended.part.partNumber);
} catch (err) {
return false;
}
});
// Fetch the information if not
if (foundIndex > -1) {
warranty.eligibilityOptions = warranties[foundIndex];
} else {
this.getDevices(warranty.device.deviceId.serialNumber).subscribe((devices: IDevice[]) => {
warranty = devices[0];
}); // http request that returns an observable of IDevice
}
warranties.push(warranty);
}
});
return observableOf(warranties);
}
private mapelibilitystobulk(可观察的):可观察的{
常量保证:IDevice[]=[];
bulk.subscribe((bulk:any[])=>{
用于(批量保修){
//检查另一台设备是否已具有该信息
const foundIndex=保修。findIndex((扩展:IDevice)=>{
试一试{
退货保修.device.stockKeepingId.equals(扩展的.part.part号);
}捕捉(错误){
返回false;
}
});
//如果没有,请获取信息
如果(foundIndex>-1){
warranty.eligibilityOptions=保修[foundIndex];
}否则{
this.getDevices(warranty.device.deviceId.serialNumber)。订阅((设备:IDevice[])=>{
保修=设备[0];
});//返回IDevice的可观察值的http请求
}
保修。推送(保修);
}
});
返回可观察的(保证);
}
目前,我的代码立即返回一个可观察的数组,但是,它是空的,并且没有我想要的反应方式。任何建议或推荐阅读将不胜感激 如果不了解更多关于您的数据以及什么是有意义的,就不可能给出您需要的确切代码。然而,我做了一些假设,并将其放在一起,以展示一种可能的方法。这里的一个大假设是数据是可分组的,而您实际上试图实现的是仅对每个唯一的
保修.device.stockKeepingId
进行一次http调用
我将这段代码作为您的起点,希望它能让您更接近您想要实现的目标。根据StackBlitz,以下是相关方法:
public mapEligibilitiesToBulk(bulk: Warranty[]): Observable<IDevice[]> {
return from(bulk).pipe(
tap(warranty => console.log('in tap - warranty is ', warranty)),
groupBy(warranty => warranty.device.stockKeepingId),
mergeMap(group$ => group$.pipe(reduce((acc, cur) => [...acc, cur], []))),
tap(group => console.log('in tap - group is ', group)),
concatMap(group => this.getDevices(group[0].device.deviceId.serialNumber)),
tap(device => console.log('in tap - got this device back from api: ', device)),
toArray()
)
}
public Mapelibilities Tobulk(批量:保修[]):可观察{
从(散装)管道返回(
tap(保修=>console.log('在tap中-保修为',保修)),
groupBy(保修=>warranty.device.stockKeepingId),
合并映射(组$=>组$.pipe(减少((acc,cur)=>[…acc,cur]),
点击(group=>console.log('in-tap-group is',group'),
concatMap(组=>this.getDevices(组[0].device.deviceId.serialNumber)),
点击(device=>console.log('in-tap-get this device from-api:',device'),
toArray()
)
}
有几件事需要注意:
- 确保打开控制台查看结果
- 我将第一个参数更改为数组,而不是可观察的,假设您需要一个完整的数组作为开始。让我知道,如果你想扩展一个现有的可观察的,这是很容易实现的
- 我加入了一些tap()以便您可以看到代码在两个重要点上的作用
- 在StackBlitz中,当前的
为每个调用返回相同的内容,我这样做是为了简化模拟,而不是因为我相信它会以这种方式工作。:)李>getDevices()
保修.device.stockKeepingId
分组。其他提示:不要在订阅中订阅,事实上,我怀疑您不希望在这个函数中有任何订阅;希望创建数据流,让操作符函数为您工作,而不是所有这些命令代码;如果可能的话,试着只在一个地方订阅-建立一个可观察的链。