RxJS - Как получить доступ к значению BehaviorSubject после операций - PullRequest
0 голосов
/ 05 февраля 2019

Скажем, у меня есть тема поведения, переданная через одну или две операции:

const inputNumber = new BehaviorSubject(2);

// The current number can be retrieved with `inputNumber.getValue()`

const numberAfterOperations = inputNumber.pipe(
  filter(a => (a+1) % 2), // filter out odd numbers
  map(a => a * a), // square it
);

Как получить доступ к значению numberAfterOperations?

// Does not work because `getValue` is not defined!
numberAfterOperations.getValue(); // I expect this to be 4

inputNumber.next(4);

// Does not work!
numberAfterOperations.getValue(); // I expect this to be 16

Примечание: наблюдаемая подписка здесь работает нормально.Я спрашиваю о синхронном доступе к .value (или .getValue())

Я заметил подобную проблему здесь, но не увидел разрешение: https://github.com/ReactiveX/rxjs/issues/2378

Ответы [ 4 ]

0 голосов
/ 18 февраля 2019

Спасибо за ответы, ребята.Вы помогли мне понять, что не существует встроенного способа делать то, что я хотел, с предметами поведения.Я получил следующее:

function mapBehaviorSubject(behavior, mapFn) {
  const mappedSubject = new BehaviorSubject(mapFn(behavior.getValue()));
  behavior.subscribe({
    next: value => mappedSubject.next(mapFn(value)),
  });
  return mappedSubject;
}

Это позволяет мне иметь желаемое поведение:

const inputNumber = new BehaviorSubject(2);

const numberAfterOperations = mapBehaviorSubject(inputNumber, x => x * x);

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

0 голосов
/ 06 февраля 2019

Observable.pipe() возвращает Observable, поэтому, если вы хотите иметь доступ к фактическому BehaviourSubject, вы должны также передать его.

const inputNumber = new BehaviorSubject(2);

// The current number can be retrieved with `inputNumber.getValue()`

const numberAfterOperations = inputNumber.pipe(
  filter(a => (a+1) % 2), // filter out odd numbers
  map(a => a * a), // square it
  map(n => [n, inputNumber])
);

// ...later

numberAfterOperations.subscribe(([number, subject]) => {
  sbject.next(n/2);
});

Но это не должно быть сделано, вы можете четкоувидеть анти-шаблон.Сделайте .next отдельным методом и импортируйте его, где необходимо.

0 голосов
/ 06 февраля 2019

Pipe устанавливает новую наблюдаемую, которая ничего не делает, пока не подписана.Это не предмет поведения, доступ к значению которого можно получить с помощью getValue.Вы должны подписаться на него, или это холодная наблюдаемая, и нет никаких данных, идущих вниз по течению вообще.Поместите console.log в функцию карты, и вы увидите, что он даже не вызывается, если нет подписки.

Вы можете написать функцию развертки, если вы на 100% уверены, что подписка будет работатьсинхронно, как это будет, если он получен из объекта BehaviorSubject, но если вы передадите асинхронную наблюдаемую, результаты будут непредсказуемыми, скорее всего, с возвращением неопределенного.

const { BehaviorSubject } = rxjs;
const { filter, map } = rxjs.operators;

const inputNumber$ = new BehaviorSubject(2);

const numberAfterOperations$ = inputNumber$.pipe(
  filter(a => (a+1) % 2), // filter out odd numbers
  map(a => { console.log('mapping'); return a * a; }), // square it
);

inputNumber$.next(4);

console.log('No mapping has happened yet');

console.log(unwrap(numberAfterOperations$));

function unwrap(obs$) {
  let value;
  const sub = obs$.subscribe(val => { value = val; });
  sub.unsubscribe();
  return value;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>

Если вы используете Angular, вы можете использовать асинхронную трубу в представлении

{{ numberAfterOperations | async }}
0 голосов
/ 06 февраля 2019

Я думаю, вы не понимаете, как работают Observables / Subjects.Субъект не имеет значения 4 или 16 в примерах, которые вы показали, это производное путем применения ваших конвейерных операций через получившиеся наблюдаемые.Вам нужно будет использовать оператор, такой как first() или take(1), чтобы получить значение между вызовами к next по теме.Субъект знает только о значениях, которые были отправлены через него с next, он не знает, как наблюдаемые, которые могут быть прикреплены к нему, решают изменить это значение.

...