Сила RxJS. scan + mergeScan = 'Загрузить еще'
Кнопка 'Загрузить еще' (либо автоматическая подгрузка данных при скролле) довольно часто встречается в проектах и обычно решение связано с большим количеством подписок и переменных.
Как всегда, для оптимизации чего либо нам на помощь приходит великий и могучий RxJS, а в данной ситуации конкретно операторы scan & mergeScan .
Код:
readonly loadTrigger$ = new Subject<void>();
private readonly batchSize = 5;
private readonly posts$ = this.loadTrigger$.pipe(
startWith(void 0),
scan((offset) => offset + this.batchSize, -this.batchSize),
mergeScan(
(accPosts: Post[], offset: number) =>
getPosts(offset, this.batchSize).pipe(
map((newPosts) => [...accPosts, ...newPosts]),
),
[] as Post[],
),
);
scan – калькулятор + хранитель состояния для offset:
Управляет состоянием загрузки (текущее смещение)
Начинается с -batchSize, чтобы первая загрузка была с 0
Увеличивает смещение на batchSize при каждом срабатывании
mergeScan – волшебный оператор для инкрементальной загрузки:
Сохраняет массив накопленных постов
Объединяет новые данные с существующими
Корректно обрабатывает параллельные запросы (в отличие от обычного scan)
Где полезен этот паттерн?
Постраничные API (пагинация)
Бесконечная прокрутка
Порционная загрузка данных
Любые сценарии накопления асинхронных данных
scan - https://rxjs.dev/api/operators/scan mergeScan - https://rxjs.dev/api/operators/mergeScan Больше об Angular - https://t.me/grandgular