Un servicio está obteniendo datos de API y necesito conservarlos y usarlos en muchos otros componentes cada vez que cambia la URL (enlaces de enrutador) sin volver a llamar a API. Api debe buscar solo cuando se ejecuta el servicio.
Necesito hacer que el método del componente espere hasta que los datos estén disponibles.
(Código real reducido al mínimo para facilitar la lectura)
constructor(private http: HttpClient) { this.fetchData(); } fetchData(): void { this.http.get(this.endpointUrl).subscribe((res)=>{ this.data = res }); } getData(selectedCategory): DataType { return this.data.find(cat => cat === selectedCategory) } ngOnInit(): void { this.activatedRoute.paramMap.subscribe( (params: ParamMap) => { // I need params before calling service method // this method must wait until the "data" is available in service. this.selectedCategory = this.service.getData(params.category); } ); }Sin muchos cambios, sería posible suscribirse a fetchData() que, en cambio, devuelve un transporte de datos solicitado observable. Usamos tap para el efecto secundario de configurar también this.data en el Servicio. ¡No olvides darte de unsubscribe() ! También tenga en cuenta algunos errores de sintaxis, no los verifiqué. Sugiriendo agregar tipos para <any> .
fetchData(): Observable<any>{ return this.http.get(this.endpointUrl).pipe( tap(res => this.data = res), catchError(console.log(err)) ) } ngOnInit(): void { this.activatedRoute.paramMap.subscribe( (params: ParamMap) => { this.myService.fetchData().subscribe(res => { this.selectedCategory = this.service.getData(params.category); // Or use // this.selectedCategory = this.res.find(cat => cat === params.category) }); } ); } Aunque no se recomienda suscribirse al servicio (especialmente al servicio onRoot ) porque el servicio hará una solicitud cada vez que cambie la URL, pero supongo que esto es lo que desea. Así que ten cuidado.
Nos suscribimos a los cambios de parámetros en el constructor. El servicio solicitará nuevos datos en cada cambio de ruta. Los datos consultados se emitirán mediante BehaviourSubject , que retiene y actualiza los datos. Los componentes pueden suscribirse a BehaviourSubject en lugar de usar | async tubería | async o suscripción manual.
Servicio:
let data = new BehaviorSubject(null); constructor() { this.activatedRoute.paramMap.subscribe( (params: ParamMap) => { this.fetchData().subscribe(res => { this.data.next(res); }); } ); }Sugeriría usar la tubería asíncrona (si necesita mostrar los datos) y debería evitar anidar suscripciones.
Para la persistencia de datos sobre la actualización de la página, deberá usar el almacenamiento local o el almacenamiento de la sesión. No soy un gran fanático de esto, pero supongo que depende de sus requisitos.
Puede administrar su estado con la ayuda de BehaviourSubject, pero si quiere hacer cosas más complicadas y mantener su código limpio, le recomendaré usar una biblioteca de administración de estado como @ngrx/component-store .
Tu servicio
private readonly _state = newBehaviourSubject<Record<string, DataType>>(JSON.parse(localStore.getItem('state')) ?? {}); readonly state$ = this._state.asObservable(); getData(category: string) { return of(category).pipe( withLatestFrom(this.state$), // you don't want to do something like this.state.pipe(...) because you'll resubscribe to it multiple times because the implementation below switchMap(([key, data]) => { if (key in data) return of(data[key]); // return the found category return this.http.get(this.endpointUrl).pipe( tap(res => { const updatedData = { ...data, [key]: res }; this._state.next(updatedData); // update your state localStorage.setItem('state', JSON.stringify(updatedData) // update local storage }) ); } ) }Componente
readonly selectedCategory$ = this.activatedRoute.paramMap.pipe( map(paramMap => paramMap.get('category')), // I assume that you expect a string filter(category => !!category) // it makes sure that the result is not null or undefined switchMap(category => this.service.getData(category)), catchError(error => {...}), // handle your errors filter(res => !!res) // if you want to make sure the response is not null )