I have 3 observable arrays like below.
persons = [
{
"firstName":"john",
"lastName":"public",
"locationID":"1",
"departmentID":"100"
},
{
"firstName":"sam",
"lastName":"smith",
"locationID":"2",
"departmentID":"101"
}
]
departments = [{"departmentID": "100",
"name": "development"
},
{"departmentID": "101",
"name": "sales"
}]
locations = [{"locationID": "1", "name": "chicago"},
{"locationID":"2", "name": "ny"}]
I am trying to combine these 3 into below result ,
result = [
{
"firstName":"john",
"lastName":"public",
"location":"development",
"department":"sales"
},
{
"firstName":"sam",
"lastName":"smith",
"location":"ny",
"department":"sales"
}
]
To get the desired result, I have used map function on persons observable to give new object array.
this.store<Person>('persons')
.map(function(person){
let p = new personDetail()
p.firstName = person.firstName,
p.lastName = person.lastName
return p;
})
PersonDetail
object has firstName
, lastName
, location
and department
properties. How do I do a lookup into departments observable and get a matching row for departmentID
to get the department name ?
I am new to rxjs library, please let me know if there is a better way to attain the desired result.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With