Кернер Денис
Что такое RxJS
Для чего оно нужно
О функциональном программировании
Примеры
О RxJS
Примеры
Итоги
Библиотека для работы с событиями и потоками данных
Интенсивно используется в Angular
Давайте изучать?
Кривая изучения RxJS без попытки понять основы функционального программирования.
// левая часть - определение функции
// правая часть - выражение которое ее вычисляет
// = означает что левую часть можно заменять правой,
// в выражениях использующих эту функцию
f(x) = y
f(x) = 2 * x
f(x) = x * x
// и т.д.
function concatAll(array) {
function concatAllAcc(element, accumulator) {
if (!Array.isArray(element)) {
accumulator.push(element);
} else {
if (element.length > 0) {
concatAllAcc(element[0], accumulator);
concatAllAcc(element.slice(1), accumulator);
}
}
}
let res = [];
concatAllAcc(array, res);
return res;
}
Несмотря на всю академичность, ФП вполне успешно применяется в продакшне:
Подходы из ФП активно проникают и в другие языки,
например лямбды и потоки в java 8
Проблема: Обработка событий на колбэках сложна и чревата ошибками. Callback hell
Частичное решение: Промисы
Полное решение: RxJS
Голливудский принцип:
Есть два вида работы с коллекциями - когда мы сами запрашиваем значения (pull), и когда мы подписываемся на получение новых значений (push).
Observer next *(error|complete)?
Observable = Iterable * Observer
var observable = new Observable(function (observer) {
observer.next(1);
observer.next(2);
setTimeout(() => {
observer.next(3);
observer.complete();
}, 1000);
});
console.log('just before subscribe');
observable.subscribe({
next: x => console.log('got value ' + x),
error: err => console.error('error occurred: ' + err),
complete: () => console.log('done'),
});
console.log('just after subscribe');
just before subscribe
got value 1
got value 2
just after subscribe
got value 3
done
Пока не будет подписки через метод subscribe - мы не получим никаких значений.
Это еще называется cold observables
В операторах и их сочетаниях с помощью pipe
Типы операторов:
Marble diagrams = диаграммы c шариками
Временная ось. слева направо
Значения что посылает Observable
Успешное
завершение
Пунктир показывает трансформацию значений исходного Observable. Прямоугольник показывает
оператор
Новый Observable - результат оператора
Ошибка трансформации, не умеем переворачивать круги
import { map, switchMap, throttle } from 'rxjs/operators';
myObservable
.pipe(map(data => data * 2), switchMap(...), throttle(...))
.subscribe(...);
Пример: автокомплит
const { fromEvent } = Rx;
const { map, throttleTime, filter } = RxOperators;
fromEvent(document, 'mousemove').pipe(
map(event => event.clientX),
filter(x => x > 300),
throttleTime(300)
)
const searchBox = document.getElementById('search-box');
const typeahead = fromEvent(searchBox, 'input').pipe(
map((e: KeyboardEvent) => e.target.value),
filter(text => text.length > 2),
debounceTime(10),
distinctUntilChanged(),
switchMap(() => ajax('/api/endpoint'))
);
typeahead.subscribe(data => {
// Handle the data from the API
});
Пример: реагируем на клики только в правой части экрана
Тренируемся с rxJs:
Применяем операторы: