Search code examples
angulartypescriptapisubscriptionunsubscribe

How to unsubscribe http post request in Angular application?


Its a POST API created by API Gateway from AWS, however it always returns infinite repetition of arrays as you see in the below picture. How to return only one array?

Mutiple requests

Here's the code

Angular

import { Component, OnInit, ViewChild, OnChanges, OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http'; 
import { GetService } from '../get.service';
import { Observable, Subject } from 'rxjs';
import { IonSlides, IonSlide } from '@ionic/angular';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit   {
  protected ngUnsubscribe: Subject<void> = new Subject<void>();


constructor(public http:HttpClient) {}
  @ViewChild(IonSlides,{'static':false}) slides: IonSlides;

  slideOpts = {
    initialSlide: 1,
    speed: 400
 };
public result:any
public res:any
data:Observable<any>;
ata:Observable<any>;

ngOnInit(){
}

  getdata(){


   this.ata=this.http.post("XXXXXXXXXXXXXXXXXXXXXXXXX",{"freq":1});
   this.ata.subscribe(data=>{console.log(data)})

  return   this.res




}
INDEX:any

slideChanged() {

  this.INDEX =this.slides.getActiveIndex().then(data=>console.log(data))
  return this.INDEX

}
   }

HTML

   <ion-header>
  <ion-toolbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-toolbar>
</ion-header>
<p *ngFor="let a of getdata()">{{a}}</p >
<ion-card>
  <ion-card-content>
  <ion-slides  [options]="slideOpts" (ionSlideWillChange)="slideChanged()">
    <ion-slide  >
        <h1></h1>
    </ion-slide>
s


  </ion-slides>
</ion-card-content>
</ion-card>

Solution

  • That is not the API. Why am I sure about this? Because you're using Angular's HttpClient and you need quite a bit of boilerplate around it to make multiple requests. Your issue is because your page is renderer multiple times while Angular's rendered manages the page layout.

    The real issue lies at this line:

    <p *ngFor="let a of getdata()">{{a}}</p >
    

    Everytime that line is rendered angular calls getdata() issuing another request.

    You must decouple the result list from the function requesting it. From your code seems like ata is an Observable. Something like the following should work:

    <p *ngFor="let a of ata | async">{{a}}</p>
    

    Please note the async pipe used.

    From Angular documentation

    The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

    Of course you must call getdata() somewhere and usually the right place is in ngOnInit().

    Side note: How to get only one response from an Observable subscription

    Since in this question there is confusion on this topic if you need to get only one response from an Observable the common way is to use take operator.

    import { take } from 'rxjs/operators';
    
    [...]
    
    someService.getObservable(...)
               .pipe( take(1) ) // <-- take first response
               .subscribe( (r) => { ... } );