在我正在开发的Angular Web-Application中,我需要使用Observable
来做很多事情。
通常Observable
用于异步事件序列,但是,对我来说,通常只有1个结果(来自http请求)。
我经常需要做一些复杂的映射,以从http请求中获得所需的结果。但是,只有满足某些条件时才需要此映射,否则我可以跳过整个映射部分并返回默认值
例如:
我想获得给定article
中特定city
的销售总额
获得结果需要以下步骤:
client
s,其中包含city
city.getClients():Observable<Array<Client>>
(http GET
- &gt; Observable<Array<Client>>
)article
个给定client
的销售额
(flatMap
- &gt; Observable<Array<ClientSale>>
)article
个给定client
的总销售额
(map
- &gt; Observable<Array<number>>
)map
- &gt; Observable<number>
)现在有可能,那个城市没有client
生活
在这种情况下,可以跳过步骤2-4,并且可以使用值onNext
调用0
- 回调。
请注意,这只是一个简单的例子,用于解释我想要做的事情。真正的用例需要更多步骤,我需要做一个
if (meetsCondition(x))
return map(x);
else
return defaultValue;
每一步。
filter
- 函数几乎就是我要找的。但是,它不会为过滤后的值调用onNext
。
有没有办法实现我想要的目标?
修改
我将尝试在问题中添加更多细节:
我的应用程序中有很多延迟加载的数据。因此,如果您请求city
,则无法加载相关的client
,直到您通过调用getClients
请求它们为止。
因此,大多数getter
返回Observable
数据而不是数据本身。
现在我经常需要通过组合不同来源的值(client
,article
等)来计算事物。
通常这种计算可以在中间停止,因为无法确定有效结果
如果值为空,则可能是这种情况,但如果筛选的列表包含多个条目,则也是如此。
如果我能够做到这样的话,那么对我来说完美的解决方案就是:
client.getOrders()
.skipIf(value => !meetsCondition(value), defaultValue)
.map(value => mapValue(value)) // Probably not called
.map(value => mapValueAgain(value)) // Probably not called
.subscribe(value => {
if (value == defaultValue)
console.log("Skip");
else
console.log(value)
});
答案 0 :(得分:2)
我构建了你的案例,如下所示。正确?
function getClients(city:string) {
return Observable.of(city == 'Seoul' ? ['c1', 'c2'] : []).delay(100);
}
function getSales(client:string, article:string) {
let sales:any = {
'c1': {
'item1': 10,
'item2': 20
},
'c2': {
'item1': 30,
'item2': 40
}
};
return Observable.of(sales[client][article]).delay(100);
}
let city = 'Seoul';
let article = 'item2';
getClients(city)
.mergeMap(clients => {
console.log('>> mergeMap');
let salesObs = clients.map<Observable<number>>(client => getSales(client, article));
return Observable.merge(salesObs).mergeAll();
})
.reduce((sum, sales) => {
console.log('>> reduce');
return sum + sales;
}, 0)
.subscribe(value => console.log(`sum = ${value}`));
虽然在这种情况下客户端为空,但没有问题。将城市更改为其他值并尝试。
我添加了一些代码,以便在一般情况下使用&#39; map&#39;并且&#39;赶上&#39; 如果它符合某些跳过条件,那么&#39; mergeMap&#39;并且&#39;减少&#39;没有被解雇。
getClients(city)
.map(clients => {
// some skip condition
if (clients.length == 0)
throw 0 /* default value */;
return clients;
})
.mergeMap(clients => {
console.log('>> mergeMap');
let salesObs = clients.map<Observable<number>>(client => getSales(client, article));
return Observable.merge(salesObs).mergeAll();
})
.reduce((sum, sales) => {
console.log('>> reduce');
return sum + sales;
}, 0)
.catch((err, caught) => {
console.log('>> catch');
// default value
return Observable.of(err);
})
.subscribe(value => console.log(`sum = ${value}`));