每个Subject都是一个Observable。给定一个Subject,就可以订阅它,提供一个Observable,它将开始正常地接收值。从Observer的角度看,他不能说明Observable执行是来自一个普通的单播Observable还是一个Subject。
在Subject内部,subscribe不调用传递值的新执行。他只是在Observers列表中注册给定的Observer, 类似于addListener在其他库和语言中的工作方式。
每个Subject都是Observer。他是一个具有next(v),error(e)和complete()方法的对象。要向Subject提供一个新值,只需调用next(theValue), 他就会多播给注册来监听Subject的Observers。
下面例子,我们有两个Observers连接到一个Subject,将一些值提供给Subject:
const subject = new Subject<number>();
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`),
});
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`),
});
subject.next(1);
subject.next(2);
// Logs:
// observerA: 1
// observerB: 1
// observerA: 2
// observerB: 2
因为Subject是一个Observer,这也意味着你可以提供一个Subject作为任何Observable的订阅的参数。如下:
const subject = new Subject<number>();
subject.subscribe({
next: (v) => console.log(`observerA: ${v}`),
});
subject.subscribe({
next: (v) => console.log(`observerB: ${v}`),
});
const observable = from([1, 2, 3]);
observable.subscribe(subject); // You can subscribe providing a Subject
// Logs:
// observerA: 1
// observerB: 1
// observerA: 2
// observerB: 2
// observerA: 3
// observerB: 3
如上,我们实际上只是通过Subject将单播Observable执行转换为多播。这演示了如何让任何Observable执行共享给多个Observers的唯一方法是Subject。
还有一些特殊的Subject类型:BehaviorSubject, ReplaySubject, 和 AsyncSubject.
Multicasted Observables
“多播Observable”通过一个可能有许多订阅者的 Subject 传递通知,而普通的“单播Observable”只向单个Observer发送通知。
一个多播的Observable使用一个幕后的Subject让多个Observers看到相同的Observable执行。
在幕后,多播operator是这样工作的:Observers订阅底层的Subject,Subject订阅源Observable。以下示例与前面使用observable.subscribe(subject)的示例类似:
const source = from([1, 2, 3]);
const subject = new Subject();
const multicasted = source.pipe(multicast(subject));
// These are, under the hood, `subject.subscribe({...})`:
multicasted.subscribe({
next: (v) => console.log(`observerA: ${v}`),
});
multicasted.subscribe({
next: (v) => console.log(`observerB: ${v}`),
});
// This is, under the hood, `source.subscribe(subject)`:
multicasted.connect();
多播返回一个看起来像普通Observable的Observable,但是在订阅时像 Subject 一样工作。多播返回一个 ConnectableObserver,它只是一个connect()方法的Observable。
connect()方法对于确定共享Observable执行何时开始非常重要。因为connect()在底层执行 source.subscribe(subject) ,所以connect()返回一个Subscription,您可以unsubscribe,以取消共享的Observable执行。
Angular项目应用场景
比如在一个service中通过API获取某项data,而我有很多组件需要用这个data。可以这么写
const subject = new Subject();
// componentA
subject.subscribe({
next: (v) => console.log(`componentA: ${v}`),
});
// componentB
subject.subscribe({
next: (v) => console.log(`componentB: ${v}`),
});
// service
setTimeout(()=>{
subject.next('response data')
}, 3000)
// Logs:
// componentA: response data
// componentB: response data
参考: RxJS - Subject