If you want to handle that only with Observable (which seems to be a good idea within an effect), here's how you could do it :
const { Observable } = Rx;
// DATA
const user = {
id: 'currentUserId',
accountIds: [
'accountId0',
'accountId1',
'accountId2',
'accountId3'
]
}
// MOCK BACKEND CALLS
const apiService = {
post: (url, data) => {
return Observable.of(`some response for ${url}`).delay(1000);
}
};
// HANDLE THE MULTIPLE HTTP CALLS
Observable
.from(user.accountIds)
.map(accountId => ({ id: accountId, userIds: [user.id] }))
.map(account => apiService.post(`/accounts/${account.id}`, account))
.concatAll()
.do(console.log)
.last()
.do(_ => console.log('Finished to chain the HTTP calls for accounts'))
.switchMap(_ => apiService.post(`/users/${user.id}`, user))
.do(console.log)
.subscribe();
The output is :

I've made a Plunkr so you can see it in action :
https://plnkr.co/edit/xFWXyAJM6qm0XwMf4tmv?p=preview
The interesting part here is how we handle the calls.
Let me give you some more details about that :
from
allows us to send every accountIds
one by one down the observable :
.from(user.accountIds)
Then we can build for every accountId
the Object we want to send to the backend :
.map(accountId => ({ id: accountId, userIds: [user.id] }))
Once it's done, we create a cold Observable which will make the HTTP call once we subscribe to it :
.map(account => apiService.post(`/accounts/${account.id}`, account))
Thanks to concatAll
, we have the behavior that you're expecting : Making every HTTP calls one by one :
.concatAll()
Display the response of an HTTP call :
.do(console.log)
Well now, we'd like to make a final request to users
once every request to accounts
are done. last
will help us wait for the last one (captain obvious here) :
.last()
Simply log that every requests to accounts
are done
.do(_ => console.log('Finished to chain the HTTP calls for accounts'))
Make the final HTTP call to users
.switchMap(_ => apiService.post(/users/${user.id}
, user))
Output the response
.do(console.log)
And of course we need to subscribe as this is a cold Observable otherwise nothing would happen. *
.subscribe();
*: In your effect, you might want to simply return the Observable as ngrx/effects will subscribe to it for you ;)