Я пишу приложение Angular, которое использует IndexedDB для кеширования данных.
Всякий раз, когда приложение собирается выполнить определенный HTTP-вызов на сервер Я хотел бы получить эти данные из IndexedDB и дополнить или заменить ответ сервера.
Проблема в том, что получение данных из IndexedDB является асинхронной операцией, которая возвращает Observable, и я не могу вернуть измененные данные обратно в вызывающую службу.
Перехватчик выглядит так:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).map((event) => {
if (event instanceof HttpResponse) {
console.info("before cacheResponseProccess");
const val: Observable<HttpEvent<any>> = this.angularCache.cacheResponseProccess(event);
val.subscribe(x => {
console.info('Return modified response is:');
console.info(x);
return x;
});
}
}).catch((error, caught) => {
return Observable.throw(error);
});
}
См. Образец проблемы на https://stackblitz.com/edit/angular-owqgb6





Вам нужно вернуть вещи в операторе map (возвращение значений в обратных вызовах асинхронного режима на самом деле не вернет их внешней функции). Кроме того, когда вы получаете асинхронный результат для замены исходного HttpResponse, вы можете изменить оператор map на mergeMap и вернуть в нем Observable.
Попробуйте использовать приведенный ниже пример кода:
return next.handle(req).mergeMap((event) => { // use mergeMap instead of map
return new Observable(ob => { // return new Observable to retrieve asynchronous data
if (event instanceof HttpResponse) {
console.info("before cacheResponseProccess");
const val: Observable<HttpEvent<any>> = this.angularCache.cacheResponseProccess(event);
val.subscribe(x => {
console.info('Return modified response is:', x);
ob.next(x); // return modified result
});
}
});
}).catch((error, caught) => {
return Observable.throw(error);
});
Исправлен демонстрация.
Вы можете сделать что-то вроде этого:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url.indexOf('https://api.someurl.com/') > -1) {
let authReq: HttpRequest<any> = req;
return this.authService.getCurrentSession().pipe(
mergeMap(
(session: Session) => {
const token: string = session.getToken();
authReq = req.clone({
headers: req.headers.set('Authorization', token)
});
return next.handle(authReq);
}
),
catchError(
(error) => {
console.error('Intercept error, couldn\'t add authorisation headers', error.message);
next.handle(authReq);
return of(error);
}
)
);
} else {
return next.handle(req);
}
}