I have 3 dependent Rest API resources (lets say observables) like this:
1st observable produces one item as array of users, like this:
getUsers(): Observable<User[]>
[
{
"id": 1,
"name": "Peter",
"surname": "Smith"
},
{
"id": 2,
"name": "John",
"surname": "Wayne"
},
...
]
2nd observable can be used to fetch addresses assigned to user, so the input parameter is User ID, and returns a one item as array of addresses:
getUserAddresses(user_id: string): Observable<Address[]>
[
{
"id": 1,
"city": "London",
"street": "Wicombe 34"
},
{
"id": 2,
"city": "Paris",
"street": "La fever 20"
},
...
]
3rd observable can be used to fetch companies assigned to user, so the input parameter is User ID, and returns a one item as array of companies:
getUserCompanies(user_id: string): Observable<Company[]>
[
{
"id": 1,
"name": "Fintch CO",
"state": "France"
},
{
"id": 2,
"name": "C&C inc.",
"state": "USA"
},
...
]
I want to chain these 3 observables into one which will produce the result again as one item, that will contain array of users with their additional addresses arrays and companies array, like following:
[
{
"id": 1,
"name": "Peter",
"surname": "Smith",
"addreesses":
[
{
"id": "1",
"city": "London",
"street": "Wicombe 34"
},
{
"id": "2",
"city": "",
"street": "La fever 20"
}
],
"companies":
[
{
"id": "1",
"name": "Fintch CO",
"state": "France"
},
{
"id": "2",
"name": "C&C inc.",
"state": "USA"
}
]
}
},
{
"id": 2,
"name": "John",
"surname": "Wayne",
"addresses": [...],
"companies": [...],
},
...
]
How should look like the operators composite to achieve that in Angular 6 with RxJs 6? Thanks a lot for advice.
Something like this could work
getUsers()
.pipe(
switchMap(users => from(users)),
mergeMap(user => forkJoin(getAddresses(user.id), getCompanies(user.id))
.pipe(map(data => ({user, addresses: data[0], companies: data[1] })))
tap(data => data.user.addresses = data.addresses),
tap(data => data.user.companies = data.companies),
map(data => data.user),
toArray()
)
)
Applied to a different use case a similar chain is explained in more details here .
To chain observables, you can use the flatMap
function. This function is like promises then, meaning the function is only executed once the observable has resolved to a value.
There is also an observable function called forkJoin
which allows you to wait for multiple async requests to all have resolved to a value.
Example:
getUsers().flatMap((users) => {
// the users variable is the list of users
var multipleObservables = [];
users.forEach((u) => {
multipleObservables.push(
getUserAddresses(u.id).map((usersAddresses) => {
u.addresses = usersAddresses;
return u;
});
);
});
return forkJoin(multipleObservables);
}).flatMap((usersWithAddresses) => {
// the usersWithAddresses variable is an array of users which also have their addresses
var multipleObservables = [];
usersWithAddresses.forEach((u) => {
multipleObservables.push(
getUserCompanies(u.id).map((usersCompanies) => {
u.companies = usersCompanies;
return u;
});
);
});
return forkJoin(multipleObservables);
});
You can write something like this to chain you request and grow your user objects.
Here are the operators for combination, these emit the result in an array ( reference ):
I would suggest giving them all a read, to work out what you would prefer and find best for your scenario.
Hope this helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.