RxJS — Как получать подписчику только новые значения?

В Angular, для получения только новых значений от Observable используется оператор distinctUntilChanged() из библиотеки RxJS.

RxJS (Reactive Extensions for JavaScript) - это библиотека для работы с асинхронными и событийными потоками данных в JavaScript. Она является неотъемлемой частью Angular и предоставляет мощные инструменты для работы с асинхронными операциями.

Оператор distinctUntilChanged() позволяет фильтровать поток значений, чтобы получить только уникальные значения, причем повторяющиеся значения будут пропущены. Он сравнивает текущее значение с предыдущим и пропускает только те значения, которые отличаются от предыдущего. Если значение идентично предыдущему, оно будет проигнорировано.

Пример использования:

import { Observable, from } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

const values: Observable<number> = from([1, 1, 2, 2, 3, 4, 5]);

values
  .pipe(distinctUntilChanged())
  .subscribe(value => console.log(value));

// Вывод:
// 1
// 2
// 3
// 4
// 5

В этом примере мы создаем Observable, который содержит последовательность чисел. Затем мы используем оператор pipe() для применения оператора distinctUntilChanged() к потоку значений. В итоге, в консоль будут выведены только уникальные значения: 1, 2, 3, 4 и 5.

Также, оператор distinctUntilChanged() может принимать в качестве аргумента функцию, которая определяет, как сравнивать значения. Это позволяет настраивать логику сравнения в зависимости от ваших потребностей. Например, вы можете использовать эту функцию для сравнения объектов по определенным свойствам.

import { Observable, from } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

const values: Observable<{ id: number, name: string }> = from([
  { id: 1, name: 'John' },
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 2, name: 'Jane' },
  { id: 3, name: 'Mike' },
]);

const compareFn = (prevValue, curValue) => prevValue.id === curValue.id;

values
  .pipe(distinctUntilChanged(compareFn))
  .subscribe(value => console.log(value));

// Вывод:
// { id: 1, name: 'John' }
// { id: 2, name: 'Jane' }
// { id: 3, name: 'Mike' }

В этом примере мы создаем Observable, который содержит объекты с идентификаторами и именами. Затем мы передаем функцию compareFn в качестве аргумента оператору distinctUntilChanged(). Эта функция сравнивает значения по идентификатору. В результате, в консоль будут выведены только уникальные объекты с разными идентификаторами: { id: 1, name: 'John' }, { id: 2, name: 'Jane' } и { id: 3, name: 'Mike' }.

Важно отметить, что оператор distinctUntilChanged() работает только внутри одной подписки. Это означает, что при каждой новой подписке оператор будет сравнивать значения от начала. Если вы хотите сохранять уникальные значения между подписками, вам нужно использовать оператор shareReplay().

Вывод: оператор distinctUntilChanged() позволяет получать только новые значения от Observable путем фильтрации повторяющихся значений. Он может быть полезен для множества сценариев в Angular, например, для обновления представления только при изменении данных или для отслеживания уникальных действий пользователя.