这节举几个例子来加强 Subject 的理解
例1 理解 Subject 的组播
代码语言:javascript复制const subject = new rxjs.Subject();
// subject.subscribe 可以理解成 Event.AddListener 注意只是注册不会去执行
// subscriber 1
subject.subscribe((data) => {
console.log(data); // 0.24957144215097515 (random number)
});
// subscriber 2
subject.subscribe((data) => {
console.log(data); // 0.24957144215097515 (random number)
});
// 执行每个注册的 Listener
// 注意 输出的随机数值是一样的
subject.next(Math.random());
Subject 是一个特殊的对象,即可以是数据生产者也同时是消费者,通过使用 Subject 作为数据消费者,可以使用它们将 Observables 从单播转换为多播。下面是一个例子:
例2 使用 Subject 将 Observables 从单播转换为多播
代码语言:javascript复制const observable = rxjs.Observable
.create((observer) => {
observer.next(Math.random());
});
const subject = new rxjs.Subject();
// subscriber 1
subject.subscribe((data) => {
console.log(data); // 0.24957144215097515 (random number)
});
// subscriber 2
subject.subscribe((data) => {
console.log(data); // 0.24957144215097515 (random number)
});
observable.subscribe(subject);
结合 Angular 中的例子
例1
实现文本框传送输入内容并防抖
部分关键代码, TS 部分
代码语言:javascript复制nameChange$ = new Subject<string>();
// val 就是 input 输入的值
this.nameChange$.pipe(debounceTime(800)).subscribe(val => {
// 交互后台
this.service.searchName(val).subscribe(
// ....
);
});
模板
代码语言:javascript复制 <input matInput type="text" placeholder="Search Keyword" name="keyword"
(input)="nameChange$.next($event.target.value)" [(ngModel)]="formData.keyword">
Subject 实际上就是 Observer Pattern 的实现,他会在内部管理一份 observer 的清单,并在接收到值时遍历这份清单并送出值,所以我们可以直接用 subject 的 next 方法传送值,所有订阅的 observer 就会接收到值了。
例2
使用 subject 可以实现局部刷新页面功能,假设有一List列表组件,单击列表中的某按钮弹出Model,操作完Model要刷新List数据。 我们可以按如下操作:
代码语言:javascript复制// 第一步 先在 service 文件中定义一个 subject
export class ListService {
listUpdated$ = new Subject();
}
// 第二步 在列表组件中 ,组件初始化时把要执行的事件放到 subject 中
// 非常类似 DOM addEventListener
export class ListComponent implements OnInit {
ngOnInit() {
this.service.listUpdated$.subscribe(() => {
this.getListData();
});
}
// 从后台获取数据的方法
private getListData() {
}
}
// 第三步 在需要的地方调用定义的subject
export class InfoModalComponent implements OnInit {
onAddClick(): void {
// 重新获取最新数据
this.service.listUpdated$.next();
}
}
总结:
- Subject 是一个特殊的对象,即可以是数据生产者也同时是消费者,通过使用 Subject 作为数据消费者,可以使用它们将 Observables 从单播转换为多播。下面是一个例子:
- Subject 很像 EventEmitter,用来维护注册的 Listener, 当对 Subject 调用 subscribe 时,不会执行发送数据,只是在 维护的 Observers 中注册新的 Observer。