我在SO中进行了搜索,发现了与Observables有关的类似问题,但没有一个对我的特定用例有所帮助,我必须假定这是一个非常常见的用例。
我正在调用REST API(通过http模块)以获取Quote
对象。自然地,它返回一个Observable<Quote>
。
我还正在调用另一个REST API(同样通过http模块)来获取QuoteLineItem[]
。同样,这自然会返回一个Observable<QuoteLineItem[]>
。
理想情况下,客户端代码只能检索Observable<Quote>
并且可以使用Quote.LineItems。
最佳做法是什么?我可以提出两种选择:
1-订阅Observable时,从Observable<QuoteLineItem[]>
填充Quote.LineItems。我一直在努力做到这一点,但我似乎没有这样做。这是代码,但是不确定什么地方出错了?
// This will change to an http call
const subj: BehaviorSubject<Quote> = new BehaviorSubject(quote)
const obs: Observable<Quote> = subj.asObservable();
// Now try to get LineItems within the observable and populate Quote.LineItems
obs.pipe(switchMap((q: Quote) => {
this.quoteLineItemService.getLineItems(quoteId).subscribe((data: QuoteLineItem[]) => {
q.lineItems = data
return q
},
error => console.error(error)
)
}))
return obs;
此代码遇到编译错误:无法将类型'(q:any)=> void'的参数分配给类型'(value:any,index:number)=> ObservableInput'的参数。 不能将类型“ void”分配给类型“ ObservableInput”。
我的第一个问题是,我在这里做错了什么?我该怎么办?
2-以上是最佳做法,还是我应该在Quote对象中将Observable<QuoteLineItem[]>
而不是QuoteLineItem[]
作为属性?
很抱歉,如果这些是非常基本的问题。一如既往,非常感谢您的帮助!
答案 0 :(得分:0)
对我来说,选项1似乎足够合理。唯一的问题是,回调的参数类型应为switchMap((q: Quote)...
,大写字母 Q 而不是switchMap((q: quote)
。接口/类型名称区分大小写。如果我理解正确,您的模型称为Quote
,而您的成员变量称为quote
。我相信是错误的根源。
答案 1 :(得分:0)
如果您无权访问要返回实现模型的后端服务,那么两次调用选项就算不错。
要填充Quote对象,您可以返回Quote Promise,以简化代码。
然后向服务器发出双重请求。
const getQuote = (id: any): Promise<Quote> => {
return new Promise<Quote>((resolve, reject) => {
const obs: Observable<Quote> = subject.asObservable(); // Mocked HTTP call
obs.subscribe((q: Quote) => {
quoteLineItemService.getLineItems(q.id).subscribe(
(items: QuoteLineItem[]) => {
q.items = items;
resolve(q);
},
(err: Error) => {
console.error(err);
reject(err);
}
);
});
});
}
getQuote(1)
.then((q: Quote) => {
// Populated quote
console.log(q);
})
.catch(_ => {/* handle error */});