У меня возникли проблемы с получением суммы (или любого уменьшения) внутреннего числового свойства Observable в другом Observable.
У меня есть наблюдаемый массив объектов Account (Observable<AppAccount[]>
).
export interface AppAccount {
_id?: string;
name: string;
}
И наблюдаемый массив объектов Balance, каждый из которых имеет accountId. с учетной записью может быть связано много балансов (отсортировано / отфильтровано по дате, но эта часть удалена для краткости)
export interface AccountBalance {
_id?: string;
accountId: string;
amount: number;
}
У меня есть вспомогательный метод, который возвращает только последнюю сумму объекта Balance для данной учетной записи.
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}`)),
);
}
Теперь я пытаюсь написать метод, который будет перебирать учетные записи, вызывать getLastAmount () для каждого, а затем суммировать их все и возвращать Observable. Вот что мне удалось до сих пор:
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)
);
}
Но это, кажется, никогда не вернется и застревает в бесконечном цикле ??
Имея только одну учетную запись и один связанный баланс, с балансом, имеющим «сумму» «10», я получаю это из моего журнала консоли: «0 + 10» снова и снова, и сетевой журнал также подтверждает, что он вызывает getBalances ( ) непрерывно.
Я на правильном пути? Есть ли способ лучше? Почему этот канал RXJS застревает в петле?
ИЗМЕНИТЬ: я внес некоторые изменения на основе предложений Пиччи:
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))
);
}
Но это все равно не возвращается, или труба не достраивает? Я сделал stackblitz здесь: https://stackblitz.com/edit/angular-rxjs-nested-obsv Если вы проверите вывод консоли, он, похоже, не продвинется дальше вызова forkJoin ...
reduce
, который отправит уменьшенное значение, когда источник (accounts$
в данном случае) завершится. Если вы хотите получать значения на каждой итерации уменьшения, вы можете использоватьscan
. - person Andrei Gătej   schedule 21.07.2020