我正在尝试创建一个表单来提交详细信息,但是当我订阅该服务时,订阅会完成两次。第一个是空数据,第二个是实际数据。
组件.ts
addBook() {
this.errorMessage = null;
this.fireService.getBook(this.bookDetails.isbn).subscribe(data => {
console.log('subscribe called');
if (null != data) {
this.dbox.open(DialogBoxComponent, {
data: { title: 'Error', content: 'Book is already present in Library. Select Edit book to modify the details', button: false }
});
this.errorMessage = 'Book is already present in Library. Select Edit book to modify the details';
} else {
this.fireService.addBook(this.bookDetails);
this.dbox.open(DialogBoxComponent, {
data: { title: 'Success', content: 'Book has been Added to Database', button: false }
});
this.router.navigateByUrl('/add-book');
}
});
}
服务.ts
getBook(id) {
console.log('called firebase get book');
return this.db.doc(`/books/${id}`).valueChanges();
}
下图是chrome控制台的图片。这表明订阅被调用了两次,但 Firebase 服务没有被调用。
chrome 控制台日志
called firebase get book
subscribe called
subscribe called
请帮忙
这是因为当 Books 集合发生变化时, getBooks 返回的 observable 会发出一个新值。第一次没有具有相同 isbn 的书,因此数据为空。然后你添加一本书,所以 same observable 再次触发,这次是你刚刚添加的书
如果您只想获取一次数据, 您可以使用 take 只订阅一次。
this.fireService.getBook(this.bookDetails.isbn).take(1).subscribe(data => {
console.log('subscribe called');
就像 Chau Tran 所说,您可以过滤以获得有效的响应。如果您还没有,我会添加一种取消订阅的方式。在下面的代码中,
this.alive
是一个 true 字段,在 OnDestory 生命挂钩中变为 false。
this.fireService.getBook(this.bookDetails.isbn)
.takeWhile(() => this.alive)
.filter(data => !!data)
.subscribe(...)
使用管道(take(1))
this.fireService.getBook(this.bookDetails.isbn).pipe(take(1)).
subscribe(data => { console.log('subscribe called');
在函数
addBook
中,您正在调用订阅。每次调用函数addBook
时,您都在进行订阅调用,请避免在此类函数中使用订阅。确保仅在 onInit()
中订阅,以便每当您进行更改时它都会检查。
我遇到了类似的问题,问题是订阅设置了两次,订阅观察者的函数在 ngOnChanges 中被调用,并且 ngOnChanges 被意外调用了两次。修复 ngOnChanges 调用两次也解决了这个问题