我已经使用Angular / RxJS已有几周了,并且具有根据多个REST请求构建的各种模型,到目前为止,我已经使用switchMap()实现了该模型.这是一个简单的示例(stackblitz:https://stackblitz.com/edit/angular-o1djbb):
import { Component,OnInit,} from '@angular/core';
import { Observable,of } from 'rxjs';
import { delay,switchMap } from 'rxjs/operators';
interface Order {
id: string;
itemName: string;
details?: string;
}
@Component({
selector: 'my-app',templateUrl: './app.component.html',styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
order: Order;
ngOnInit() {
this.getOrderFromApi(123)
.subscribe(item => this.order = item);
}
getOrderFromApi(id): Observable<Order> {
const item$= this.getItemName(id);
const fullItem$= item$.pipe(
switchMap(n => {
console.log(`Got name: '${n}''`);
return this.getDetails(n);
},(nameReq,detailsReq) => ({ id: '123',itemName: nameReq,details: detailsReq })
));
return fullItem$;
}
getItemName(id): Observable<string> {
return this.fakeXhr('foo');
}
getDetails(itemName): Observable<string> {
console.log(`Got details '${itemName}''`)
return this.fakeXhr('Some details about foo');
}
fakeXhr(payload: any) {
return of(payload)
.pipe(delay(2000));
}
}
和一个简单的模板:
<p>
item: {{order && order.itemName}}
</p>
<p>
details: {{order && order.details}}
</p>
这可行,但是直到两个请求都完成,订单信息才会呈现.我想让itemName在可用时立即呈现,然后在可用时呈现细节.因此,利用了Observables可以发出的多个值.例如:
// first value emitted:
{ itemName: 'foo',details: null }
// second value emitted:
{ itemName: 'foo',details: 'Some details about foo' }
我意识到我可能可以通过BehavIoUrSubject或Redux来实现(就像我过去使用React一样),但是由于所有这些对我来说都是新事物,所以我觉得我没有一个简单的解决方案.
最佳答案
使用
expand
直接从第一个请求发出数据,然后执行第二个请求.
expand将递归调用内部请求,从上一个请求中获取订单作为输入,因此,我们仅在订单没有详细信息时才执行第二个请求,否则以EMPTY Observable结束递归.
import { Observable,EMPTY } from 'rxjs';
import { map,expand } from 'rxjs/operators';
getOrderFromApi(id): Observable<Order> {
return this.getItemName(id).pipe(
map(itemName => ({ id,itemName,details: null } as Order)),expand(order => order.details
? EMPTY
: this.getDetails(order.itemName).pipe(
map(details => ({ id,itemName: order.itemName,details } as Order))
)
)
);
}
https://stackblitz.com/edit/angular-umqyem
返回的Observable将发出:
> {“ id”:123,“ itemName”:“ foo”,“ details”:null}
> {“ id”:123,“ details”:“有关foo的一些详细信息”}