I'm using angular Http Interceptor to catch request and, in case that these request were already made, the interceptor just returns the HttpResponse cached on a service.
The interceptors fires with this piece of code that makes request to the API:
getSeriesWithGenres() {
const series$ = this.getSeries()
const genres$ = this.getGenres()
return forkJoin([series$, genres$]).pipe(
map(([series, genres]) => {
return series.map((serie: Serie) => {
serie.genre_ids = serie.genre_ids.map(genreId => {
return genres.find((genre: Genre) => genre.id === genreId)?.name
})
return serie
})
})
)
}
And the methods getSeries() and getGenres() made the Http Request as follows:
getSeries() {
return this.http
.get<ApiResponse>(
`
https://api.themoviedb.org/3/tv/popular?api_key=${environment.apiKey}&language=en-US
`
)
.pipe(map((data: ApiResponse) => data.results as Serie[]))
}
getGenres() {
return this.http
.get(
`
https://api.themoviedb.org/3/genre/tv/list?api_key=${environment.apiKey}&language=en-US
`
)
.pipe(map((data: any) => data.genres))
}
So, my problem is when I cached the response, because if method called getSeriesWithGenres() fires twice, Iḿ getting the following error:
TypeError: "genre_ids" is read-only
Note: To cached the response I use the following data structure on another service:
private cache: Map<string, [Date | null, HttpResponse<unknown>]> = new Map()
With the corresponding getters and setters methods
And my interceptor, use this service as follows:
const HALF_HOUR = 1800
const TIME_TO_LIVE = HALF_HOUR
@Injectable()
export class CachingInterceptor implements HttpInterceptor {
constructor(private cacheResolver: CacheResolverService) {}
intercept(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
if (request.method !== 'GET') {
return next.handle(request)
}
console.log('CachingInterceptor: ' request.url)
const cachedResponse = this.cacheResolver.get(request.url)
console.log('CachedResponse:' JSON.stringify(cachedResponse?.body))
return cachedResponse ? of(cachedResponse) : this.sendRequest(request, next)
}
sendRequest(
request: HttpRequest<unknown>,
next: HttpHandler
): Observable<HttpEvent<unknown>> {
return next.handle(request).pipe(
map((event: HttpEvent<unknown>) => {
if (event instanceof HttpResponse) {
this.cacheResolver.set(request.url, event, TIME_TO_LIVE)
}
return event
})
)
}
}
CodePudding user response:
The cache sets the content as frozen/read-only, to avoid you tampering with the cache.
Try updating the stream yourself :
getSeriesWithGenres() {
const series$ = this.getSeries()
const genres$ = this.getGenres()
return forkJoin([series$, genres$]).pipe(
map(([series, genres]) => series.map(serie => ({
...serie,
genre_ids: serie.genre_ids.map(
genreId => genres.find((genre: Genre) => genre.id === genreId)?.name
)
}))),
)
}