I am trying to sharereplay()
of my httpClient request between multiple components by using the following configuration:
apicaller.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// import rxjs map
import { map, shareReplay } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class ApicallerService {
peopleindex: number = 1;
constructor(private _http: HttpClient) {}
private readonly request = this._http
.get('https://swapi.dev/api/people/' this.peopleindex)
.pipe(shareReplay());
getData(peopleindex: number = 1) {
this.peopleindex = peopleindex;
return this.request;
}
}
Component1
Should request api to get the details for the id 2
import { Component, OnInit } from '@angular/core';
import { ApicallerService } from '../apicaller.service';
@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.css'],
})
export class Component1Component implements OnInit {
apiresponse: any;
editRes: any;
constructor(private _apicaller: ApicallerService) {}
ngOnInit(): void {
this._apicaller.getData(2).subscribe((data: any[]) => { // <-- Notice 2 in the argument
console.log(data);
this.apiresponse = data;
});
}
}
Component2
Requests for the default id
import { Component, OnInit } from '@angular/core';
import { ApicallerService } from '../apicaller.service';
@Component({
selector: 'app-component2',
templateUrl: './component2.component.html',
styleUrls: ['./component2.component.css']
})
export class Component2Component implements OnInit {
apiresponse: any = {};
constructor(
private _apicaller: ApicallerService
) { }
ngOnInit(): void {
// get data from api using service
this._apicaller.getData().subscribe(
(data) => {
this.apiresponse = data;
}
);
}
}
However, a new request with the peopleindex = 2
is not being made by component1
To reproduce, you can use my stackblitz setup: https://stackblitz.com/edit/angular-ivy-gdxyy6?file=src/app/component1/component1.component.ts
CodePudding user response:
I would suggest to create API store for such case.
for first time it will store API with specific id to store and return initial call.
for second time it will take stored API
export class ApicallerService {
apiStore = new Map();
constructor(private _http: HttpClient) {}
private getApiRequest(id) {
return this._http.get('https://swapi.dev/api/people/' id).pipe(shareReplay());
}
getData(peopleindex: number = 1) {
if (!this.apiStore.has(peopleindex)) {
this.apiStore.set(peopleindex, this.getApiRequest(peopleindex));
}
return this.apiStore.get(peopleindex);
}
}
CodePudding user response:
ShareReplay will be beneficial, if you have call for some metadata(masterdata), that will not change across the components(cached/sharing the same data).
To execute the expression with the new values you will need to add getter for request insteed of field.
private get request() {
return this._http.get('https://swapi.dev/api/people/' this.peopleindex);
}
The pattern most of the people uses for calling httpServices is like this.
Create a separate service that calls rest endpoints(wrapper around httpClient).
@Injectable({
providedIn: 'root',
})
export class ApiService {
constructor(private _http: HttpClient) {}
get(url: string) {
return this._http
.get(url);
}
post(url: string, data) {
return this._http
.post(url, data);
}
}
Then add your feature service that will depend on apiService.
@Injectable({
providedIn: 'root',
})
export class PeopleService {
constructor(private _api: ApiService) {}
getData(peopleindex: number = 1) {
console.log(peopleindex);
return this._api
.get('https://swapi.dev/api/people/' peopleindex);
}
}
Call these feature services from your feature components.
export class Component1Component implements OnInit {
apiresponse: any;
editRes: any;
constructor(private _peopleService: PeopleService) {}
ngOnInit(): void {
this._peopleService.getData(2).subscribe((data: any[]) => {
this.apiresponse = data;
});
}
}
export class Component2Component implements OnInit {
apiresponse: any = {};
constructor(
private _peopleService: PeopleService
) { }
ngOnInit(): void {
// get data from api using service
this._peopleService.getData().subscribe(
(data) => {
console.log(data);
this.apiresponse = data;
}
);
}
}
Here is stackblitz link for same.