Home > Enterprise >  Manipulate the data and avoid multiple API calls
Manipulate the data and avoid multiple API calls

Time:06-01

I am using angular (v11) service to fetch data from backend. I want to call the api only once and change the data (title).

The problem is that createPicture() is called Everytime when I change the title? I am seeing a api call in the network tab of the browser.

How to avoid calling each time I call createPicture function and serve the data calling the api once and storing it to a memory? so I can change title without waiting too long.

private async createPicture(
    pictureSize:PictureSize = PictureSize.A1,
    title: string
  ) {
    const svgs: CarInfo[] = await this.apiCall
      .images(false, false)
      .toPromise();

    const pics: ImageConf[] = svgs.map((info, i) => ({
      types: 'car',
      side: i   '',
      svg: this.reportService.svgToString(info.svg)
    }));
    return pics.map((pic) => {
      const template = new DataTemplate(
        {
          content: pic.svg,
          ruler: {
            size: 50,
            tickCount: 4,
          },
          infos: this.getPicturesInfo(
            pic.types,
            title // change without calling API?
          ),
        },
        this,
        pic
        );
      return { side: pic.side, svg: template.render(pictureSize) };
    });
  }

title is inside const template can I separate it somehow? I have heard about Behaviour Subject but I am not sure how it would in my case.

  getCarImage(pictureSize,title) {
    const [cars,company]= await promise.all([
    this.createPicture(pictureSize,title),
    rhis.companyInfo(pictureSize,title)
    ]);
const images = [...cars.slice(0,4) ...company,...cars.slice(4)]
const collectionCars = images.map(({imgData}) => imgData) 
    return img
    }

this is how I am using it in my component..

myComponent.ts

const getData(){
this.form.valueChanges.pipe().subscribe(changes =>{
this.ServiceCar.getImage(changes.pictureSize,changes.title).then()...
})
}

CodePudding user response:

The problem mainly arises because Observables and Promises do not like to be mixed in general. I would recommend to follow Angular recommendations and try to do everything possible the rxjs-way (Observable) and avoid Promises where possible.

Your specific problem seems to arise in your "myComponent.ts":

const getData(){
  this.form.valueChanges.pipe().subscribe(changes =>{
    this.ServiceCar.getImage(changes.pictureSize,changes.title).then()...
  })
}

By subscribing to the valueChanges observable provided by your FormGroup you receive an event whenever the value of your form changes. And every time you receive a change you call for a new picture. I would guess that your title is part of your form (?) which would explain the reloads.

If that is the case and the problem, then adding the first() operator in your pipe should fix this, although I struggle to understand why you would subscribe to valueChanges in the first place.

CodePudding user response:

The reason why you have a Http call per change is that you are obviously putting the API endpoint method inside the valueChanges multicasting observable which is listening to the changes happening in the FormControls, FormGroup or FormArray properties. Thus, whenever a change occurs it fires (emits) your Http call. You can control this by pointing to the concerned formControlName directly and setTimeOut it since you are using Promise based flow. However as pointed in the comment above, Angular is working best with RxJs event streams operators. If you are to use Observables from RxJs operators, you can check out debounceTime operator. Seems you are exactly looking for this one in your use case.

According to docs:

"[debounceTime] Emits a notification from the source Observable only after a particular time span has passed without another source emission."

  • Related