很抱歉,如果在其他地方得到解答,我试图搜索,但我甚至不确定我在寻找什么。
假设我有这个对象可以使用:
userRequest: {
id: number,
subject: string,
...
orderIds: number[]
...
}
order: {
id: number,
...
clientId: number,
productIds: number[]
}
client: {
id: number,
name: string,
...
}
product: {
id: number,
name: string,
price: number
}
现在,用户将在某个时刻使用该复合对象填充表单并将其发送以进行分析。但在发送之前,首先要进行验证。我无法在表单中进行验证,因为用户只是输入纸上收到的数据。如果数据为"无效",将发送更多信息请求。
因此,我需要验证请求,还需要验证订单,产品和客户端。我被要求出示一个"验证请求"屏幕和每个元素被检查后,"有效"或"无效"屏幕。很简单。
但是现在,我发送http请求并让Observables处理。我试图更多地了解他们和所有可用的操作员以及如何混合他们,但此刻,我完全迷失了。
所以,我首先从服务器获得Observable<userRequest>
。然后,一旦我收到了userRequest,我需要从他们的id中获取所有订单,当我得到一个&#34; order&#34;时,我必须得到客户端&amp;他的产品。
所有这些都是异步完成的,但在收到订单之前我无法获得客户端或产品,我需要userRequest来提供订单。此外,当我收到订单时,我需要同时获得客户和产品的同时#34;因为他们都需要相同的订单......?对于最后的结局,对于我得到的每个元素(请求,订单,客户,产品),我需要验证它并等待每个元素说出&#34;请求有效&#34;或不。
所以要恢复:
Observable<userRequest>
并验证Observable<order[]>
并验证每个订单Observable<Client>
并验证PLUS 2)获得Observable<Product[]>
并验证每个订单步骤1和2需要按顺序执行,但是当步骤2完成时,我需要对步骤2的每个结果执行步骤3.1和3.2。等待。
我确定它远非明确,我只是希望它足够清楚,以便你们想要实现我们想要的东西。如果您对我有任何提示,请分享! ; )
我确实知道需要做些什么。但是当我失去我的酷时,就是当我需要按顺序链接Observable时(因为每个依赖于之前的那个),在不同的点我需要调用验证方法,当涉及到客户端和产品时,都需要它的订单ID。我确实尝试了许多方法,但我完全没有理解这个概念。
bygrace - 不,我不希望验证被阻止。它应该验证所有内容,因为它会导致对所有缺失或无效部分的请求,并且应该在最后显示。这就是为什么我需要一种方法来知道什么时候完成所有事情,以便我可以检查是否找到了错误。
请求,订单,客户和产品均来自各自的服务。该服务进行http resquest并返回Observable。所以我需要链接调用(当涉及到Order时,我需要为相同的Order Id获取两个Observable)。
QuietOran - 这是我尝试过的东西。我知道这太可怕了,但我现在迷路了......
onValidateRequest(requestId: number) {
this.requestService.getUserRequest$(this.requestId)
.do(request => {
this.validateRequest(request);
})
.concatMap(request => this.orderService.getOrdersForRequest$(request.id))
.do(orders => {
this.validateOrders(orders);
})
.concatMap(orders => {
// Now, this is were I'm completely lost
// I manage to get the request and the orders, but in this block, I need to get the client AND the products
// and validate each one as I receive it
// Then return something
})
.do(() => {
// when I validate an element, if there's an error, I simple add it in an array.
// So when ALL the Observable above are completed, this function simply checks
// if there's something in it
this.checkForErrors();
})
.subscribe();
}
答案 0 :(得分:0)
我会给你一些粗略的东西,你可以通过反馈来改进,因为我不清楚你想要的数据的最终形状和所有。希望这能指出你正确的方向。
基本上,如果您希望来自一个observable的数据提供给另一个observable,那么您可以使用switchmap
或其中一个堂兄弟。如果您需要输入的值以及结果,那么只需将它们与combineLatest
或类似的东西混在一起。
console.clear();
function getUserRequest(requestId) {
return Rx.Observable.of({ id: 1, subject: 'a', orderIds: [10, 20] })
.delay(500).take(1);
}
function getOrdersForRequest(requestId) {
return Rx.Observable.of([
{ id: 10, clientId: 100, productIds: [ 1000 ] },
{ id: 20, clientId: 200, productIds: [ 1001, 1002 ] }
]).delay(200).take(1);
}
function getClientForOrder(orderId) {
let client;
switch(orderId) {
case 10:
client = { id: 100, name: 'Bob' };
break;
case 20:
client = { id: 200, name: 'Alice' };
break;
}
return Rx.Observable.of(client).delay(200).take(1);
}
function getProductsForOrder(orderId) {
let products;
switch(orderId) {
case 10:
products = [{ id: 1000, name: 'p1', price: 1 }];
break;
case 20:
products = [
{ id: 1001, name: 'p1', price: 2 },
{ id: 1002, name: 'p1', price: 3 }
];
break;
}
return Rx.Observable.of(products).delay(200).take(1);
}
Rx.Observable.of(1)
.switchMap(id => Rx.Observable.combineLatest(
getUserRequest(id),
getOrdersForRequest(id)
.switchMap(orders => Rx.Observable.combineLatest(
Rx.Observable.of(orders),
Rx.Observable.combineLatest(...orders.map(o => getClientForOrder(o.id))),
Rx.Observable.combineLatest(...orders.map(o => getProductsForOrder(o.id)))
)
),
(userRequest, [orders, clients, products]) =>
({ userRequest, orders, clients, products })
)
).subscribe(x => { console.dir(x); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>
现在我按类别展平了结果。您可能希望它们嵌套或类似的东西。这只是一个粗略的过程,所以根据需要提供反馈。