I have been using Angular/RxJS for a few weeks and have various models that are built from multiple REST requests which I have thus far achieved using switchMap(). Here is a simple contrived example (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));
}
}
And a simple template:
<p>
item: {{order && order.itemName}}
</p>
<p>
details: {{order && order.details}}
</p>
This works but the order info is not rendered until both requests complete. What I would like to happen is for the itemName to render as soon as it's available and then details to render when they become available. Hence taking advantage of the multiple values that Observables can emit. Eg:
// first value emitted:
{ itemName: 'foo', details: null }
// second value emitted:
{ itemName: 'foo', details: 'Some details about foo' }
I realise I could probably achieve this with a BehaviourSubject or using Redux (as I have in the past with React), but feel there is a simple solution I can't quite grasp due to the newness of all this for me.