Вот мой подход:
src$ = src$.pipe(publish());
const wholeNumber$ = src$.pipe(
scan(
(acc, crt) => (acc | 0) > 1 ? crt + (+(acc - (acc | 0)).toPrecision(1)) : acc + crt, 0
),
map(v => (v | 0)),
filter(v => v >= 1),
);
src$.pipe(
buffer(wholeNumber$)
).subscribe();
publish
убедится, что источник не подписан несколько раз. Это также короткая версия multicast(new Subject())
, которая является способом многоадресной рассылки источника. Чтобы это работало, src$
должен излучать асинхронно, чтобы используемый Subject
мог правильно зарегистрировать своих подписчиков (wholeNumber$
и другого).
Если источник не испуская асинхронно, вы можете заставить сделать это, используя src$.pipe(observeOn(asapScheduler))
, который будет планировать каждое уведомление как обещание.
Давайте внимательно рассмотрим cb, предоставленный scan
:
(acc, crt) => (acc | 0) > 1 ? crt + (+(acc - (acc | 0)).toPrecision(1)) : acc + crt`
number | 0
совпадает с Math.trunc(number)
.
In +(acc - (acc | 0)).toPrecision(1)
:
- когда вы делаете
1.2 - 1
, вы ' получаю: 0.199...96
; с toPrecision(1)
: (1.2 - 1).toPrecision(1)
= "0.2"
. +
получит 0.2
как число.