订阅被调用两次

时间:2018-04-20 16:05:42

标签: javascript angular typescript firebase angular5

我尝试创建表单来提交详细信息但是当我订阅服务时,订阅会完成两次。首先是空数据,第二个是实际数据。

Component.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');
      }
    });
  }

Service.ts

getBook(id) {
  console.log('called firebase get book');
  return this.db.doc(`/books/${id}`).valueChanges();
}

以下是Chrome控制台的图片。这表明订阅被调用了两次,但没有调用firebase服务。

Chrome console logs: Image please click to view

chrome console logs

called firebase get book
subscribe called
subscribe called

请帮忙

3 个答案:

答案 0 :(得分:3)

这是因为当Books集合发生变化时,getBooks返回的observable会发出一个新值。第一次没有相同isbn的书,所以数据为空。然后你添加一本书,所以相同的 observable再次触发,这次是你刚刚添加的书

如果您只想获取一次数据, 你可以使用take只订阅一次。

this.fireService.getBook(this.bookDetails.isbn).take(1).subscribe(data => {
  console.log('subscribe called');

答案 1 :(得分:2)

像Chau Tran说的那样,你可以过滤以获得有效的回复。如果您还没有,我会添加一种取消订阅的方式。在下面的代码中,this.alive是一个真实的字段,并在OnDestory生命挂钩中变为false。

this.fireService.getBook(this.bookDetails.isbn)
.takeWhile(() => this.alive)
.filter(data => !!data)
.subscribe(...)

答案 2 :(得分:0)

在函数 addBook 中,您正在调用订阅。每次调用函数 addBook 时都是在进行订阅调用,请避免在此类函数中使用订阅。确保仅在 onInit() 中订阅,以便在您进行更改时进行检查。