Когда использовать asObservable () в rxjs?

87

Мне интересно, в чем польза asObservable:

Согласно документам:

Наблюдаемая последовательность, которая скрывает идентичность исходной последовательности.

Но зачем вам скрывать последовательность?

born2net
источник

Ответы:

189

Когда использовать Subject.prototype.asObservable ()

Цель этого - предотвратить утечку "стороны наблюдателя" Субъекта из API. В основном, чтобы предотвратить дырявую абстракцию, когда вы не хотите, чтобы люди могли «переходить дальше» в получившуюся наблюдаемую.

пример

(ПРИМЕЧАНИЕ: на самом деле это не то, как вы должны превращать такой источник данных в Observable, вместо этого вы должны использовать new Observableконструктор, см. Ниже).

const myAPI = {
  getData: () => {
    const subject = new Subject();
    const source = new SomeWeirdDataSource();
    source.onMessage = (data) => subject.next({ type: 'message', data });
    source.onOtherMessage = (data) => subject.next({ type: 'othermessage', data });
    return subject.asObservable();
  }
};

Теперь, когда кто-то получает наблюдаемый результат, myAPI.getData()он не может nextоценить результат:

const result = myAPI.getData();
result.next('LOL hax!'); // throws an error because `next` doesn't exist

new Observable()Хотя обычно вам следует использовать

В приведенном выше примере мы, вероятно, создаем то, чего не хотели. Во-первых, getData()он не ленив, как большинство наблюдаемых, он SomeWeirdDataSourceнемедленно создаст базовый источник данных (и, предположительно, некоторые побочные эффекты). Это также означает, что если вы retryили repeatполученная в результате наблюдаемая, она не будет работать так, как вы думаете.

Лучше инкапсулировать создание вашего источника данных в наблюдаемом, например так:

const myAPI = {
  getData: () => return new Observable(subscriber => {
    const source = new SomeWeirdDataSource();
    source.onMessage = (data) => subscriber.next({ type: 'message', data });
    source.onOtherMessage = (data) => subscriber.next({ type: 'othermessage', data });
    return () => {
      // Even better, now we can tear down the data source for cancellation!
      source.destroy();
    };
  });
}

С помощью приведенного выше кода любое поведение, в том числе «не ленивое», может быть создано поверх наблюдаемого с использованием существующих операторов RxJS.

Бен Леш
источник
3
TX Бен ... была следующим ваши вещи ... АЯ для всех большой поддержки на RX
born2net
3
@Shardul ... подписывайтесь на результат:result.subscribe(value => doSomething(value))
Бен Леш
2
@BenTaliadoros Да, каждый раз, когда ты return subject.asObservable(); это это будет новое наблюдаемое. У вас будет одна переменная-член Subject, и onMessage / onOtherMessage будет объявлен в условии или при инициализации (не при каждом вызове). Я использовал этот подход, pipe( filter() )основанный на параметре, передаваемом getData()функции. The
Drenai 04
5
@BenLesh, во втором примере кода subjectдолжно быть subscriber?
Florin D
1
Хотелось бы и здесь проверки: должны ли subject.nextбыть строчки subscriber. Кроме того, «если вы попытаетесь повторить или повторите полученную наблюдаемую, она не будет работать так, как вы думаете». Можете быть более конкретными? Вы просто имеете в виду, что new SomeWeirdDataSource()это будет происходить каждый раз, когда getDataвызывается, и что, обернув его, new Observableвы заставляете этот экземпляр ждать до подписки. Думаю, я не понимаю, когда вы звоните getDataбез знака, .subscribeпоэтому мне не хватает значения. Наконец, что, по вашему мнению, произойдет, чтобы «разрушить источник данных»? Благодарю.
1252748
7

A Subjectможет действовать как как an, так observerи как an observable.

У An Obervableесть 2 метода.

  • подписываться
  • отказаться от подписки

Каждый раз, когда вы подписываетесь на observable, вы получаетеobserver , который имеет следующую , ошибку и полные методы на нем.

Вам нужно будет скрыть последовательность, потому что вы не хотите, чтобы источник потока был общедоступным в каждом компоненте. Вы можете обратиться к @BenLeshпримеру с тем же.

PS: Когда я впервые столкнулся с реактивным Javascript, я не мог понять asObservable. Потому что мне нужно было убедиться, что я ясно понимаю основы, а затем идти дальше asObservable. :)

HV Sharma
источник