Ответ 1
Когда использовать 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' does not exist
Обычно вы должны использовать new Observable()
, хотя
В приведенном выше примере мы, вероятно, создаем что-то, чего не хотели. С одной стороны, getData()
не ленив, как большинство наблюдаемых, он сразу же создаст базовый источник данных SomeWeirdDataSource
(и, возможно, некоторые побочные эффекты). Это также означает, что если вы retry
или repeat
получите наблюдаемые результаты, они не будут работать так, как вы думаете.
Лучше инкапсулировать создание вашего источника данных в наблюдаемом виде следующим образом:
const myAPI = {
getData: () => return new Observable(subscriber => {
const source = new SomeWeirdDataSource();
source.onMessage = (data) => subject.next({ type: 'message', data });
source.onOtherMessage = (data) => subject.next({ type: 'othermessage', data });
return () => {
// Even better, now we can tear down the data source for cancellation!
source.destroy();
};
});
}
С помощью приведенного выше кода любое поведение, в том числе делающее его "не ленивым", можно создать поверх наблюдаемого, используя существующие операторы RxJS.