valueChanges observable 似乎在订阅之前订阅了数据
valueChanges observable seems to be subscribing to data before subscription
我正在创建一个动态创建的响应式表单。我以可观察对象(来自主题)的形式从服务获取数据,并希望在创建表单后订阅该表单的 valueChanges
。当我第一次设置它时,我订阅了服务的每个可观察对象和 valueChanges,但我看到了表单创建的每个步骤的数据,这是有道理的,因为两个服务可观察对象可以在之后发出。
所以我重构了设置以使用 Observable.zip
,据我所知,它使代码线性化,因此应该在我获得 valueChanges
订阅之前设置表单,但是我仍然看到表单创建的每一步都在发生。
this.filterForm = this.formBuilder.group({
'search': '',
'types': this.formBuilder.group({}),
'dates': this.formBuilder.array([]),
});
let formData = Observable.zip(
this.eventService.getTypes(),
this.eventService.getDates()
);
formData.forEach(data => {
let types = data[0],
dates = data[1];
types.forEach(type => {
this.types.push(type);
(<FormGroup>(this.filterForm.get('types'))).addControl(type, new FormControl())
});
dates.forEach(date => {
this.dates.push(date.format('dddd'));
(<FormArray>(this.filterForm.get('dates'))).push(new FormControl(false))
});
this.filterForm.valueChanges.subscribe(data => console.log(data));
});
当我说我在构建表单时看到值时,我的意思是:
{search: "", types: {…}, dates: Array(0)}
{search: "", types: {…}, dates: Array(1)}
{search: "", types: {…}, dates: Array(2)}
{search: "", types: {…}, dates: Array(3)}
{search: "", types: {…}, dates: Array(4)}
{search: "", types: {…}, dates: Array(5)}
随着类型字段的构建,它前面有十几个条目。
这应该是这样吗?我的目标是在构建表单后进行订阅,因此我只会在用户更改表单时获取值。
不要订阅 OnInit 生命周期挂钩。创建一个处理订阅的方法,并在 OnInit 中声明表单模型后调用该方法。
更一般地说,您可以使用 skip() 运算符跳过特定数量的发射,或者使用 filter/mapping 仅在满足特定条件/结构后才处理发射。
我有一点不同的建议。在 RxJS 中,除了订阅链的 subscribe()
方法之外,还有内部订阅的 toPromise()
和 forEach()
方法。参见 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Observable.ts#L223
而且我认为这就是发生在你身上的事情。 forEach
方法订阅 formData
Observable 并为发出的每个值调用其回调。但是您还在回调中使用 this.filterForm.valueChanges.subscribe
,这意味着每次 formData
发出一个值时您都会创建一个新订阅。
我不知道您的代码应该做什么,但我认为您可以将其重组为如下所示:
Observable.zip(
this.eventService.getTypes(),
this.eventService.getDates()
)
.do(data => {
let types = data[0],
dates = data[1];
types.forEach(type => {
this.types.push(type);
(<FormGroup>(this.filterForm.get('types'))).addControl(type, new FormControl())
});
dates.forEach(date => {
this.dates.push(date.format('dddd'));
(<FormArray>(this.filterForm.get('dates'))).push(new FormControl(false))
});
})
.switchMap(() => this.filterForm.valueChanges))
.subscribe(data => console.log(data));
我正在创建一个动态创建的响应式表单。我以可观察对象(来自主题)的形式从服务获取数据,并希望在创建表单后订阅该表单的 valueChanges
。当我第一次设置它时,我订阅了服务的每个可观察对象和 valueChanges,但我看到了表单创建的每个步骤的数据,这是有道理的,因为两个服务可观察对象可以在之后发出。
所以我重构了设置以使用 Observable.zip
,据我所知,它使代码线性化,因此应该在我获得 valueChanges
订阅之前设置表单,但是我仍然看到表单创建的每一步都在发生。
this.filterForm = this.formBuilder.group({
'search': '',
'types': this.formBuilder.group({}),
'dates': this.formBuilder.array([]),
});
let formData = Observable.zip(
this.eventService.getTypes(),
this.eventService.getDates()
);
formData.forEach(data => {
let types = data[0],
dates = data[1];
types.forEach(type => {
this.types.push(type);
(<FormGroup>(this.filterForm.get('types'))).addControl(type, new FormControl())
});
dates.forEach(date => {
this.dates.push(date.format('dddd'));
(<FormArray>(this.filterForm.get('dates'))).push(new FormControl(false))
});
this.filterForm.valueChanges.subscribe(data => console.log(data));
});
当我说我在构建表单时看到值时,我的意思是:
{search: "", types: {…}, dates: Array(0)}
{search: "", types: {…}, dates: Array(1)}
{search: "", types: {…}, dates: Array(2)}
{search: "", types: {…}, dates: Array(3)}
{search: "", types: {…}, dates: Array(4)}
{search: "", types: {…}, dates: Array(5)}
随着类型字段的构建,它前面有十几个条目。
这应该是这样吗?我的目标是在构建表单后进行订阅,因此我只会在用户更改表单时获取值。
不要订阅 OnInit 生命周期挂钩。创建一个处理订阅的方法,并在 OnInit 中声明表单模型后调用该方法。
更一般地说,您可以使用 skip() 运算符跳过特定数量的发射,或者使用 filter/mapping 仅在满足特定条件/结构后才处理发射。
我有一点不同的建议。在 RxJS 中,除了订阅链的 subscribe()
方法之外,还有内部订阅的 toPromise()
和 forEach()
方法。参见 https://github.com/ReactiveX/rxjs/blob/master/src/internal/Observable.ts#L223
而且我认为这就是发生在你身上的事情。 forEach
方法订阅 formData
Observable 并为发出的每个值调用其回调。但是您还在回调中使用 this.filterForm.valueChanges.subscribe
,这意味着每次 formData
发出一个值时您都会创建一个新订阅。
我不知道您的代码应该做什么,但我认为您可以将其重组为如下所示:
Observable.zip(
this.eventService.getTypes(),
this.eventService.getDates()
)
.do(data => {
let types = data[0],
dates = data[1];
types.forEach(type => {
this.types.push(type);
(<FormGroup>(this.filterForm.get('types'))).addControl(type, new FormControl())
});
dates.forEach(date => {
this.dates.push(date.format('dddd'));
(<FormArray>(this.filterForm.get('dates'))).push(new FormControl(false))
});
})
.switchMap(() => this.filterForm.valueChanges))
.subscribe(data => console.log(data));