I have 3 observable arrays like below.
persons = [
{
\"firstName\":\"john\",
\"lastName\":\"public\",
\"locationID\":\"1\",
\"depa
It's not clear what exactly your observables are emitting, so I considered two options.
let persons = [
{
"firstName":"john",
"lastName":"public",
"locationID":"1",
"departmentID":"100"
},
{
"firstName":"sam",
"lastName":"smith",
"locationID":"2",
"departmentID":"101"
}
];
let departments = [
{"departmentID": "100", "name": "development"},
{"departmentID": "101", "name": "sales"}
];
let locations = [
{"locationID": "1", "name": "chicago"},
{"locationID": "2", "name": "ny"}
];
// Option 1: first observable emits persons one by one,
// locations and departments are emitted as whole arrays.
let o1: any = Observable.from(persons);
let o2: any = Observable.of(departments);
let o3: any = Observable.of(locations);
o1.withLatestFrom(o2, o3, (p, d, l) => {
// here it is probably better to convert array to some kind of map or dictionary,
// but I'm only showing Rxjs concept of doing such things.
let location = l.find(c => c.locationID === p.locationID);
let department = d.find(c => c.departmentID === p.departmentID);
return {
firstName: p.firstName,
lastName: p.lastName,
location: location ? location.name : "",
department: department ? department.name : ""
};
}).subscribe((f) => {
console.log(f);
});
// Option 2: all observables emit elements one by one.
// In this case we need to convert departments and locations to arrays.
o1 = Observable.from(persons);
o2 = Observable.from(departments);
o3 = Observable.from(locations);
o1.withLatestFrom(o2.toArray(), o3.toArray(), (p, d, l) => {
// this part of code is exactly the same as in previous case.
let location = l.find(c => c.locationID === p.locationID);
let department = d.find(c => c.departmentID === p.departmentID);
return {
firstName: p.firstName,
lastName: p.lastName,
location: location ? location.name : "",
department: department ? department.name : ""
};
}).subscribe((f) => {
console.log(f);
});
i think the RxJS .zip operator may be your friend here.
As far as I understand, .zip emits like this ...
.zip(
Observable.from[array1].switchMap( // map to http response here ),
Observable.from[array2].switchMap( // map to http response here ),
Observable.from[array3].switchMap( // map to http response here )
).map((valueFromArray1, valueFromArray2, valueFromArray3) {
// Create your object here
})
Something like that! Hopefully, puts you on the right track.
.zip should emit the first time when all 3 have emitted (and it will emit a second time when all three stream have emitted twice, etc) - In your scenario I expect all three stream emit once only, which makes it a simple case for .zip
Since you'll very likely want to fetch lists of departments and locations from a remote service (make another HTTP request) I'd do it right away with Observables as well.
Observable.from(persons)
.mergeMap(person => {
let department$ = Observable.from(departments)
.filter(department => department.departmentID == person.departmentID);
let location$ = Observable.from(locations)
.filter(location => location.locationID == person.locationID);
return Observable.forkJoin(department$, location$, (department, location) => {
return {
'firstName': person.firstName,
'lastName': person.lastName,
'location': location.name,
'department': department.name,
};
});
})
.toArray()
.subscribe(result => console.log(result));
This prints to console:
[ { firstName: 'john',
lastName: 'public',
location: 'chicago',
department: 'development' },
{ firstName: 'sam',
lastName: 'smith',
location: 'ny',
department: 'sales' } ]
There're two Observables department$
and location$
that are filtered with filter()
operator to get the only item with matching ID. Then forkJoin() operator waits until both of them are complete. Operator mergeMap()
then reemits the value returned from forkJoin()
. At the end with toArray()
we collect all items into a single array.
Instead of Observable.from(...)
you can have whatever service you'll need (eg. http.get(...)
).
See live demo: https://jsbin.com/nenekup/4/edit?js,console
Similar questions: Merge subarrays using Observables and Subscribing to a nested Observable