Когда я впервые прочитал о Rx (в моем случае RxJS), мне было тяжело с Observables, Observers, держать их в чистоте, что они делают и т. д. и т. д. По общему признанию, я даже особо не игрался с RxJS. Однако я много читал об этом, всегда чувствуя, что просто понимаю, что происходит на самом деле.
Если потоки данных похожи на массивы, то остальное должно быть простым. Поскольку недавно я немного, но, казалось бы, прочно разобрался с Observables и Observers, я перешел к этому таинственному Rx.Subject. Это и Observable, и Observer? Что это хотя бы значит.
Это Observer и Observable
Оказывается, это именно то, что это означает. Это Observable и Observer вместе взятые. Он способен облегчить однонаправленный поток данных, поддерживаемый архитектурами, подобными React и Flux, или всем, что использует преимущества pub/sub. Когда обычные Observables, кажется, полагаются на внешний импульс для управления потоком данных через приложение, Rx.Subject управляет и направляет поток данных сам.
Один определяет Rx.Subject с аналогичной конечной целью и способом, подобным тому, как определяется Observable. Разработчик хочет каким-то образом формировать поток данных. С Observable это формирование сродни отображению функции на весь домен. Вы применяете преобразование ко всей группе данных. Rx.Subject также делает это, но вы также можете решить, как вы хотите поступить с конечным результатом. Здесь вступает в действие часть Observer.
var add = new Rx.Subject(); var store = []; add.map( value => { store.push(value); return store; }).subscribe(val => { console.log(val); }); add.onNext(0); // logs --> [0] add.onNext(1); // logs --> [0,1]
Код внутри «карты», который является «предварительной подпиской», — это то, как я решил преобразовать значение, передаваемое в Observer половину Rx.Subject через «onNext». Наблюдаемая половина Rx.Subject объясняется тем, что она обрабатывает данные как поток. Однако в этом случае источником потока данных является сам Субъект. Он прослушивает val и, когда он его получает, оперирует им, вставляя их в хранилище, а затем возвращая это хранилище.
onNext и Observer половина Subject
Часть, которая может сбить с толку незнакомого читателя, — это взаимодействие между этой функцией onNext и Subject. «onNext» — это метод наблюдателя, который катализирует действие потока данных, производимое субъектом «добавить» (действие — не технический термин, просто слово, которое я считаю подходящим). Точно так же, как Observable формирует форму потока данных, я определяю «наблюдаемую часть» с помощью карты. «map» — это просто метод, который работает с каждым элементом в последовательности. Если вы не используете Rx, вы можете использовать карту для выполнения преобразования каждого элемента в массиве. Поскольку Rx имеет дело с массивоподобными потоками данных, карта используется для выполнения операции над всем потоком. В моем случае я беру каждый элемент в потоке и вставляю его в хранилище.
Subject.map(x => { return x + 1; }).subscribe(val => { return val; }); //psuedo code-ish for i in range(0,2) Subject.onNext(i) //--> 1 //--> 2 //--> 3
«val», возвращаемый субъектом, — это не то же самое, что «val», являющееся аргументом его метода «onNext», а его преобразованная версия. Вы можете сделать что-то очень похожее с Observable и анонимной функцией в качестве Observer, но в этом случае драйвером модификации является поток данных, проходящий случайно через цепочку Observables. В этом случае Субъект является независимым субъектом. Хотя его можно использовать так же, как Observables, он имеет больше возможностей как своего рода служебная функция для приложения. Я могу вызвать метод «onNext» объекта в любом месте, чтобы сделать что-то с потоком Observable, в то время как Observables, кажется, лучше служат основной опорой приложения.
Вариант использования магазина, который я придумал для Rx.Subject, ограниченная версия которого показана выше, очень хорошо подходит для Subject. Субъект «добавить» можно использовать в качестве моста между некоторым потоком данных Observable и состоянием приложения. Я очень рад продолжить использование Rx.Subject в будущем. Возможно, я мог бы даже реализовать более общую систему хранения состояний, используя все RxJS. С этой первой встречи я думаю, что смогу использовать Субъекты для многих небольших задач. Субъект может быть использован для всего, что связано со сбором и манипулированием отдельными данными. Как, например, получение строки из поля ввода и сброс внутреннего значения ввода в пустую строку, например:
const todoInput = document.getElementById('id'); const resetInput = new Rx.Subject(); resetInput .map( val => { return ""; }) .subscribe( v => { todoInput.value = v; });