Observable - 监听 EventEmitter 并发出初始值
Observable - Listen to EventEmitter & emit initial
我目前正在尝试从 Angular Material Library 实施 table。
我需要包括分页和排序,所以我按照提供的示例 "Table with sorting" & "Table with pagination" .
不同之处在于,我使用 Angular 提供的 HttpClient
从 REST 端点获取数据。
这是当前代码(简体):
服务:
@Injectable()
export class DataService {
constructor(private http: HttpClient) {
}
getData(page: number, size: number, sort: string): Observable<Data[]> {
const params = new HttpParams()
.set('page', String(page))
.set('size', String(size))
.set('sort', String(sort));
return this.http.get<Data[]>('/api/v1/data', {params: params});
}
}
数据源:
export class DataDataSource extends DataSource<Data> {
constructor(private dataService: DataService, private sort: MdSort, private paginator: MdPaginator) {
super();
}
connect(collectionViewer: CollectionViewer): Observable<Data[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.paginator.page
];
return Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
});
}
disconnect(collectionViewer: CollectionViewer): void {
}
}
实际问题
在示例中,每次数据更改时,Behaviour
用于向 Observable
发出 Event
。
因为我使用的是 REST 端点,所以我没有这种行为。
因此,显示的 table 为空,直到发出分页或排序事件 。
如何初始触发订阅者(table)初始加载数据?
我是 JavaScript & Rx 的新手,所以如果这是一个愚蠢的问题,我已经提前道歉 :)
您创建的 Observable 目前处于冷状态,因为它没有被订阅。您应该能够通过执行以下操作来订阅可观察对象。
Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
}).subscribe(
(result) => //do something,
(err) => //do something
);
在组件中启动和订阅 Observable 时,重要的是要记住在组件销毁后取消订阅 Observable,否则它会保持热状态。为此,将订阅设置为一种方法:
subscription: Subsction;
connect(collectionViewer: CollectionViewer): Observable<Data[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.paginator.page
];
this.subscription = Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
我自己找到了解决办法。
问题不在于 Observable
很冷,因为 table 在调用 connect()
之后实际上已经订阅了 Observable
。
问题是返回的 Observable
当然不会发出任何事件,直到发生排序或分页(由于 merge()
)。
解决方案是添加一个可以调用刷新数据的触发器:
export class DataDataSource extends DataSource<Data> {
private dataChange: EventEmitter<void> = new EventEmitter<void>();
constructor(private dataService: DataService, private sort: MdSort, private paginator: MdPaginator) {
super();
}
public refreshData(): void {
this.dataChange.next(null);
}
connect(collectionViewer: CollectionViewer): Observable<Data[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.paginator.page,
this.dataChange
];
return Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
});
}
disconnect(collectionViewer: CollectionViewer): void {
}
}
我目前正在尝试从 Angular Material Library 实施 table。
我需要包括分页和排序,所以我按照提供的示例 "Table with sorting" & "Table with pagination" .
不同之处在于,我使用 Angular 提供的 HttpClient
从 REST 端点获取数据。
这是当前代码(简体):
服务:
@Injectable()
export class DataService {
constructor(private http: HttpClient) {
}
getData(page: number, size: number, sort: string): Observable<Data[]> {
const params = new HttpParams()
.set('page', String(page))
.set('size', String(size))
.set('sort', String(sort));
return this.http.get<Data[]>('/api/v1/data', {params: params});
}
}
数据源:
export class DataDataSource extends DataSource<Data> {
constructor(private dataService: DataService, private sort: MdSort, private paginator: MdPaginator) {
super();
}
connect(collectionViewer: CollectionViewer): Observable<Data[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.paginator.page
];
return Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
});
}
disconnect(collectionViewer: CollectionViewer): void {
}
}
实际问题
在示例中,每次数据更改时,Behaviour
用于向 Observable
发出 Event
。
因为我使用的是 REST 端点,所以我没有这种行为。
因此,显示的 table 为空,直到发出分页或排序事件 。
如何初始触发订阅者(table)初始加载数据?
我是 JavaScript & Rx 的新手,所以如果这是一个愚蠢的问题,我已经提前道歉 :)
您创建的 Observable 目前处于冷状态,因为它没有被订阅。您应该能够通过执行以下操作来订阅可观察对象。
Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
}).subscribe(
(result) => //do something,
(err) => //do something
);
在组件中启动和订阅 Observable 时,重要的是要记住在组件销毁后取消订阅 Observable,否则它会保持热状态。为此,将订阅设置为一种方法:
subscription: Subsction;
connect(collectionViewer: CollectionViewer): Observable<Data[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.paginator.page
];
this.subscription = Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
我自己找到了解决办法。
问题不在于 Observable
很冷,因为 table 在调用 connect()
之后实际上已经订阅了 Observable
。
问题是返回的 Observable
当然不会发出任何事件,直到发生排序或分页(由于 merge()
)。
解决方案是添加一个可以调用刷新数据的触发器:
export class DataDataSource extends DataSource<Data> {
private dataChange: EventEmitter<void> = new EventEmitter<void>();
constructor(private dataService: DataService, private sort: MdSort, private paginator: MdPaginator) {
super();
}
public refreshData(): void {
this.dataChange.next(null);
}
connect(collectionViewer: CollectionViewer): Observable<Data[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.paginator.page,
this.dataChange
];
return Observable.merge(...displayDataChanges).flatMap(() => {
let sortStr = this.sort.active + (this.sort.direction == 'asc' ? ',asc' : ',desc');
return this.dataService.getData(this.paginator.pageIndex, this.paginator.pageSize, sortStr);
});
}
disconnect(collectionViewer: CollectionViewer): void {
}
}