Я бы хотел кешировать и завершить HTTP-ответы от, например, запроса GET с определенными параметрами.
Пример варианта использования:
Предположим, я строюсервис, подобный этому:
@Injectable()
export class ProductService {
constructor(private http: HttpClient) {}
getProduct$(id: string): Observable<Product> {
return this.http.get<Product>(`${API_URL}/${id}`);
}
getProductA$(id: string): Observable<ProductA> {
return this.getProduct$(id).pipe(
// bunch of complicated operations here
};
}
getProductB$(id: string): Observable<ProductB> {
return this.getProduct$(id).pipe(
// bunch of other complicated operations here
};
}
}
Теперь по какой-то причине функция A вызывается в компоненте A, а функция B вызывается в компоненте B. Я знаю, что это можно сделать другим способом (например, top-интеллектуальный компонент уровня получает данные HTTP и передает их через входные параметры), но по какой-то причине эти два компонента являются «интеллектуальными», и каждый из них вызывает сервисную функцию.
Оба компонента загружаются на одну и ту же страницу,поэтому происходят две подписки = два HTTP-запроса к одной и той же конечной точке - хотя мы знаем, что результат, скорее всего, будет одинаковым.
Я хочу просто кэшировать ответ getProduct$
, НО я тоже хочу этосрок действия кэша истекает довольно быстро, потому что через 2 минуты Маргарет из управления продуктами собирается изменить цену продукта.
То, что я пробовал, но не работает:
По сути, я попытался сохранить словарь горячих наблюдаемых, используя shareReplay с временем окна 5 с.Я предположил, что если (исходная) наблюдаемая завершена или число подписок равно 0, то следующий подписчик просто перезапустит наблюдаемое, но, похоже, это не так.
private product$: { [productId: string]: Observable<Product> } = {};
getProduct$(id: string): Observable<Product> {
if (this.product$[id]) {
return this.product$[id];
}
this.product$[id] = this.http.get<Product>(`${API_URL}/${id}`)
.pipe(
shareReplay(1, 5000), // expire after 5s
)
);
return this.product$[id];
}
Я думалЯ могу попытаться удалить наблюдаемое из моего словаря по завершении, используя finalize или finally, но, к сожалению, они также вызываются при каждой отмене подписки.
Таким образом, решение должно быть, возможно, более сложным.
Любоепредложения?