Angular9-从2个可观察对象返回嵌套对象

时间:2020-04-05 22:13:26

标签: angular rxjs observable

我在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[]作为属性?

很抱歉,如果这些是非常基本的问题。一如既往,非常感谢您的帮助!

2 个答案:

答案 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 */});