最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Subscribe is called twice - Stack Overflow

programmeradmin5浏览0评论

I'm trying to create a form to submit the details but when I subscribe the service, the subscription is done twice. First with null data and second with actual data.

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();
}

Below is the image from the console of chrome. This shows that the subscription is called twice but not the firebase service.

Chrome console logs: Image please click to view

chrome console logs

called firebase get book
subscribe called
subscribe called

Please help

I'm trying to create a form to submit the details but when I subscribe the service, the subscription is done twice. First with null data and second with actual data.

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();
}

Below is the image from the console of chrome. This shows that the subscription is called twice but not the firebase service.

Chrome console logs: Image please click to view

chrome console logs

called firebase get book
subscribe called
subscribe called

Please help

Share Improve this question edited Apr 20, 2018 at 16:08 Abhijith asked Apr 20, 2018 at 16:05 AbhijithAbhijith 731 gold badge1 silver badge9 bronze badges 3
  • try this.fireService.getBook(this.bookDetails.isbn).pipe(filter(data => !!data)).subscribe(...) – Chau Tran Commented Apr 20, 2018 at 16:09
  • @ChauTran Tried your suggestions and i got the error saying The 'this' context of type 'void' is not assignable to method's 'this' of type 'Observable<{}>'. – Abhijith Commented Apr 20, 2018 at 17:01
  • Probably because I was using the pipable methods. Sorry, forgot to ask what version of angular/rxjs you're running. Run .filter(data => !!data) should behave the same way as well ;) – Chau Tran Commented Apr 20, 2018 at 18:28
Add a comment  | 

5 Answers 5

Reset to default 11

It is because the observable returned by getBooks emits a new value when the Books collection changes. The first time there is no book with the same isbn so data is null. Then you add one book and so the same observable fires again, this time with the book you just added

If you only want to get data once, you can use take to only subscribe once.

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

like Chau Tran said, you can filter to get a valid response. If you haven't already, I'd add in a way to unsubscribe. In the code below this.alive is a field that is true, and turned false in the OnDestory life hook.

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

use pipe(take(1))

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

With in the function addBook you are calling the subscription. Each time you call the function addBook you are making a subscription call, Avoid using subscription in such functions. Make sure to subscribe only in onInit(), so that it checks whenever you make changes.

I faced similar issue and the issue was that the subscription was set twice, the function which subscribes the observer was called in ngOnChanges and ngOnChanges was called twice accidentally. Fixing ngOnChanges called twice fixed this issue as well.

发布评论

评论列表(0)

  1. 暂无评论