I am having trouble getting the sum (or any reduction) of an inner number property of an Observable within another Observable.
I have an Observable array of "Account" objects (Observable<AppAccount[]>
).
export interface AppAccount {
_id?: string;
name: string;
}
And an Observable array of "Balance" objects, each with an accountId. many balances can be associated with an account (sorted/filtered by date, but that piece is removed for brevity)
export interface AccountBalance {
_id?: string;
accountId: string;
amount: number;
}
I have a helper method which returns just the last Balance object's Amount for a given Account.
getLastAmount(account: AppAccount): Observable<number> {
return this.balanceService.balances$.pipe(
map(balances => {
let last = balances.filter(balance => {
return balance.accountId === account._id;
}).sort().pop();
//console.log(last)
return last ? last.amount : 0;
}),
tap(amount => console.log(`getLastAmount() => ${amount}`)),
);
}
Now I am trying to write a method which will loop through the Accounts, call getLastAmount() for each, and then sum them all and return an Observable. This is what I have managed so far:
getTotalBalance(accounts$: Observable<AppAccount[]>): Observable<number> {
return accounts$.pipe(
map(accounts => from(accounts)),
mergeAll(),
mergeMap(account => this.getLastAmount(account)),
reduce((sum, current) => {
console.log(`${sum} + ${current}`);
return sum + current;
}, 0)
);
}
But this seems to never return, and gets stuck in an infinite loop??
With just one account and one balance associated, with the balance having an 'amount' of '10', I get this from my console log: '0 + 10' over and over, and the network log also confirm it is calling getBalances() continuously.
Am I on the right track? Is there a better way? Why does this RXJS pipe get stuck in a loop?
EDIT: I've made some changes based on picci's suggestions:
getTotalBalance(accounts$: Observable<AppAccount[]>): Observable<number> {
return accounts$.pipe(
map(accounts => accounts.map(account => this.getLastAmount(account))),
concatMap(balances$ => { console.log('balances$', balances$); return forkJoin(balances$); }),
tap(balances => console.log('balances', balances)),
map(balances => balances.reduce(
(amountSum, amount) => {
console.log(`${amountSum} + ${amount}`)
amountSum = amountSum + amount;
return amountSum
}, 0))
);
}
But this is still not returning, or the pipe is not completing? I've made a stackblitz here: https://stackblitz.com/edit/angular-rxjs-nested-obsv If you check the console output, it seems to not get any further than the forkJoin call...