В этой статье мы разберём основы работы JavaScript библиотеки RxJS, которая нужна для реактивного программирования, на чистом JS и в других фреймворках.
Также если интересны различные JavaScript библиотеки, то почитайте статью «Обзор JavaScript библиотеки Lodash», думаю многим будет интересно.
Работа с RxJS:
RxJS — это библиотека для создания программ с асинхронным кодом, основанных на событиях, с использованием наблюдаемых последовательностей.
Он предоставляет один базовый тип, Observable, вспомогательные типы (Observer, Schedulers, Subjects) и операторы, вдохновленные дополнительными функциями Array#extras (map, filter, reduce, every и т.д.), Что позволяет обрабатывать асинхронные события как коллекции.
ReactiveX сочетает в себе шаблон Observer с шаблоном Iterator и функциональное программирование с коллекциями, чтобы удовлетворить потребность в идеальном способе управления последовательностями событий.
Основные концепции RxJS, которые решают асинхронное управление событиями:
- Observable: представляет идею вызываемой коллекции будущих значений или событий;
- Observer: представляет собой набор обратных вызовов, который знает, как прослушивать значения, доставленные Observable;
- Subscription: представляет выполнение Observable, в первую очередь полезно для отмены выполнения;
- Operators: это чфункции, которые позволяют использовать стиль функционального программирования для работы с коллекциями с такими операциями, как map, filter, concat, reduce и т.д.;
- Subject: эквивалентен EventEmitter и является единственным способом многоадресной передачи значения или события нескольким наблюдателям;
- Schedulers: являются централизованными диспетчерами для управления параллелизмом, что позволяет нам координировать выполнение вычислений, например setTimeout или requestAnimationFrame или другие;
Первый пример:
Как обычно вы регистрируете слушателей событий:
1 | document.addEventListener('click', () => console.log('Clicked!')); |
Вместо этого, используя RxJS, вы создаете наблюдаемый объект:
1 2 3 | import { fromEvent } from 'rxjs'; fromEvent(document, 'click').subscribe(() => console.log('Clicked!')); |
Чистота:
Что делает RxJS мощным, так это его способность создавать значения с использованием чистых функций. Это означает, что ваш код менее подвержен ошибкам.
Обычно вы создаете нечистую функцию, где другие части вашего кода могут испортить ваше состояние:
1 2 | let count = 0; document.addEventListener('click', () => console.log(`Clicked ${++count} times`)); |
Используя RxJS, вы изолируете состояние:
1 2 3 4 5 6 | import { fromEvent } from 'rxjs'; import { scan } from 'rxjs/operators'; fromEvent(document, 'click') .pipe(scan(count => count + 1, 0)) .subscribe(count => console.log(`Clicked ${count} times`)); |
Оператор scan() работает так же, как reduce для массивов. Он принимает значение, которое подвергается обратному вызову. Возвращенное значение обратного вызова станет следующим значением, отображаемым при следующем запуске обратного вызова.
Поток:
RxJS имеет целый ряд операторов, которые помогают вам контролировать, как события проходят через ваши наблюдаемые.
Вот как можно разрешить не более одного щелчка в секунду с помощью простого JavaScript:
1 2 3 4 5 6 7 8 9 | let count = 0; let rate = 1000; let lastClick = Date.now() - rate; document.addEventListener('click', () => { if (Date.now() - lastClick >= rate) { console.log(`Clicked ${++count} times`); lastClick = Date.now(); } }); |
С RxJS:
1 2 3 4 5 6 7 8 9 | import { fromEvent } from 'rxjs'; import { throttleTime, scan } from 'rxjs/operators'; fromEvent(document, 'click') .pipe( throttleTime(1000), scan(count => count + 1, 0) ) .subscribe(count => console.log(`Clicked ${count} times`)); |
Другие операторы управления потоком: filter, delay, debounceTime, take, takeUntil, distinct, distinctUntilChanged и так далее.
Значения:
Вы можете преобразовать значения, переданные через ваши наблюдателей.
Вот как вы можете добавить текущую позицию x мыши для каждого щелчка на простом JavaScript:
1 2 3 4 5 6 7 8 9 10 | let count = 0; const rate = 1000; let lastClick = Date.now() - rate; document.addEventListener('click', event => { if (Date.now() - lastClick >= rate) { count += event.clientX; console.log(count); lastClick = Date.now(); } }); |
С RxJS:
1 2 3 4 5 6 7 8 9 10 | import { fromEvent } from 'rxjs'; import { throttleTime, map, scan } from 'rxjs/operators'; fromEvent(document, 'click') .pipe( throttleTime(1000), map(event => event.clientX), scan((count, clientX) => count + clientX, 0) ) .subscribe(count => console.log(count)); |
Также стоит отметить, что эта библиотека работает с разными фреймворками, такими как Vue.js и Angular.js, для них есть специальные ответвления, для Vue vue-rx, а в Angular он и так работает.
Вывод:
В этой статье вы прочитали не большой обзор на JavaScript библиотеку RxJS, а точнее основы работы с ней, и показ основных возможностей, но если быть совсем точным, то это бы перевод официальной документации.