在数组类型的 RxJS Subject 上调用 .next() 不会通知观察者
Calling .next() on an RxJS Subject which is of array type, does not notify observer
我正在构建一个过滤器,您可以在其中按类别进行过滤,您可以通过单击类别名称旁边的复选框来 select 一个类别。
所以我有一个 filterComponent
,它包含自己的过滤器,然后是一个 filterService
,它有一个 categories 属性是一个Subject<Array<ICategory>>
,这个属性用于将数据传递到我订阅类别属性的productsComponent
。
当我想使用此模式传递一个简单的字符串时,此逻辑有效,但当我想传递对象数组时,它似乎不起作用。
在我的 filters.component.html 文件中,当复选框值发生变化时我调用了一个方法:
<li *ngFor="let category of categories">
<mat-checkbox (change)="addOrRemoveCategory(category)" [(ngModel)]="category.isChecked">
{{'category.' + category.Name | translate}}
</mat-checkbox>
</li>
addOrRemoveCategory 方法实现如下所示:
private addOrRemoveCategory(category: ICategory): void {
if (!this.chosenCategories.includes(category)) {
this.add(category);
} else {
this.remove(category);
}
this.filterService.categories.next(this.chosenCategories);
}
所以无论类别发生了什么,添加或删除,(我在内部修改 chosenCategories 数组,我用它的值调用 .next()),我是使用更新后的数组调用 .next()。
问题是,当 chosenCategories 数组为空时,我推送到它,并用它调用 .next(),我正确地得到了我的值subscriber 函数,但是如果再次执行此操作,并且我有一个 2 元素数组,并且我调用 .next(this.chosenCategories),我的 subscriber 方法不会收到通知。
然而,一旦我用一个空数组调用 .next() 后,我的订阅者方法就会再次收到通知(因为我已经删除了所有之前 selected 的类别)。
订阅者方法:
this.categoriesChangeSubscription = this.filterService.categories
.pipe(
debounceTime(500),
distinctUntilChanged()
)
.subscribe((categories: Array<ICategory>) => {
this.categories = categories.map(category => category.Name);
this.loadData();
});
我是不是做错了什么?我必须以不同于字符串的方式处理数组吗?
结论:如果我用作 .next() 参数的数组发生变化:
- 从长度 0 到 1,我收到通知,
- 如果长度从 1 变为 0,我会收到通知,
- 但如果长度从 1 变为 2,或 5-6,或 8 变为 7,我不会收到通知
我的猜测是 distinctUntilChanged() 会过滤掉您更改的数组,因为从技术上讲它与以前的对象相同。
您可以通过克隆数组来解决:
this.filterService.categories.next([...this.chosenCategories]);
更多解决方案在a similar question.
下
我正在构建一个过滤器,您可以在其中按类别进行过滤,您可以通过单击类别名称旁边的复选框来 select 一个类别。
所以我有一个 filterComponent
,它包含自己的过滤器,然后是一个 filterService
,它有一个 categories 属性是一个Subject<Array<ICategory>>
,这个属性用于将数据传递到我订阅类别属性的productsComponent
。
当我想使用此模式传递一个简单的字符串时,此逻辑有效,但当我想传递对象数组时,它似乎不起作用。
在我的 filters.component.html 文件中,当复选框值发生变化时我调用了一个方法:
<li *ngFor="let category of categories">
<mat-checkbox (change)="addOrRemoveCategory(category)" [(ngModel)]="category.isChecked">
{{'category.' + category.Name | translate}}
</mat-checkbox>
</li>
addOrRemoveCategory 方法实现如下所示:
private addOrRemoveCategory(category: ICategory): void {
if (!this.chosenCategories.includes(category)) {
this.add(category);
} else {
this.remove(category);
}
this.filterService.categories.next(this.chosenCategories);
}
所以无论类别发生了什么,添加或删除,(我在内部修改 chosenCategories 数组,我用它的值调用 .next()),我是使用更新后的数组调用 .next()。
问题是,当 chosenCategories 数组为空时,我推送到它,并用它调用 .next(),我正确地得到了我的值subscriber 函数,但是如果再次执行此操作,并且我有一个 2 元素数组,并且我调用 .next(this.chosenCategories),我的 subscriber 方法不会收到通知。
然而,一旦我用一个空数组调用 .next() 后,我的订阅者方法就会再次收到通知(因为我已经删除了所有之前 selected 的类别)。
订阅者方法:
this.categoriesChangeSubscription = this.filterService.categories
.pipe(
debounceTime(500),
distinctUntilChanged()
)
.subscribe((categories: Array<ICategory>) => {
this.categories = categories.map(category => category.Name);
this.loadData();
});
我是不是做错了什么?我必须以不同于字符串的方式处理数组吗?
结论:如果我用作 .next() 参数的数组发生变化:
- 从长度 0 到 1,我收到通知,
- 如果长度从 1 变为 0,我会收到通知,
- 但如果长度从 1 变为 2,或 5-6,或 8 变为 7,我不会收到通知
我的猜测是 distinctUntilChanged() 会过滤掉您更改的数组,因为从技术上讲它与以前的对象相同。
您可以通过克隆数组来解决:
this.filterService.categories.next([...this.chosenCategories]);
更多解决方案在a similar question.
下