Я пытаюсь прочитать перехватчик из моего кэша, чтобы проверить, был ли кеширован почтовый запрос, когда я не в сети. Если это так, я бы вместо этого вернул кэшированные локальные данные и отобразил бы их. Кеш использует кеш-память Ionic.
В этом примере у меня просто проверяется один шаблон URL (api / dfrs / id), и это значение кэшируется. Я перебираю кеш и получаю значение, если установлен определенный ключ. Каждое значение кэша является самим запросом post.
Значение в конечном итоге найдено, но поскольку метод для получения значения является асинхронным, код перехватчика продолжается до возвращения кэшированного результата.
Итак, две проблемы, которые я пытаюсь решить
1) Выполнить код в первом операторе if для этого метода обещания
2) Вернуть тело кэшированного запросакак наблюдаемый, так что мой взгляд может использовать его
Любая помощь будет очень признательна.
token.interceptor
`
import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse, HttpHeaders, HttpResponse } from '@angular/common/http';
import { Observable, throwError, BehaviorSubject, from, EMPTY, NEVER, of } from 'rxjs';
import { catchError, filter, take, switchMap, finalize, map } from 'rxjs/operators';
import { AuthService } from '../admin/users/auth.service';
import { Router } from '@angular/router';
import { Storage, IonicStorageModule } from '@ionic/storage';
import { CacheSaveDataService } from './cache-save-data.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(public authService: AuthService, public cacheSaveDataService: CacheSaveDataService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (!this.cacheSaveDataService.status.connected && request.method === 'GET' &&
request.url.indexOf('api/dfrs/id/') !== -1) {
return next.handle(request).pipe (
map((event: any) => {
let val = this.getCachedResult(request);
return (Observable.create(val));
})
)
} else if (!this.cacheSaveDataService.status.connected && request.url.indexOf('authenticate') === -1
&& request.url.indexOf('logout') === -1 && (request.method === 'PUT' || request.method === 'POST')) {
const result = this.cacheSaveDataService.setStorageRequest(request);
return next.handle(request).pipe(
map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
console.log('event--->>>', event);
}
return event;
}),
catchError((error: HttpErrorResponse) => {
let data = {};
data = {
reason: error && error.error && error.error.reason ? error.error.reason : '',
status: error.status
};
return throwError(error);
}));
} else {
const userId = this.getUserId();
if (this.authService.getJwtToken()) {
request = this.addToken(request, this.authService.getJwtToken(), userId);
}
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
if (error.status === 405) { //|| error.status === 500) {
this.authService.backToLogin();
}
console.log('error, not logged in');
return throwError(error);
}
}));
}
console.log ('Done Intercepter');
}
async getCachedResult(request) {
const keys = await this.cacheSaveDataService.getKeys();
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (key.indexOf('reqcache') !== -1) {
return await this.getKeyValue(key, request);
}
}
}
async getKeyValue(key, request) {
const res = await this.cacheSaveDataService.get2(key);
const val: any = res;
if (val.url === request.url) {
return val;
}
}
private addToken(request: HttpRequest<any>, token: string, userId: string) {
const headers = new HttpHeaders({
'Authorization': `Bearer ${token}`,
'userId': userId
});
return request.clone({headers});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
const userId = this.getUserId();
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.authService.refreshToken().pipe(
switchMap((token: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(token.jwt);
return next.handle(this.addToken(request, token.jwt, userId));
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt, userId));
}));
}
}
private getUserId() {
const user: any = JSON.parse(localStorage.getItem('user') );
let userId = '0';
if (user !== undefined && user !== null) {
userId = user._id;
}
return userId;
}
}
`
cache-save-data.service.ts `
import { Injectable } from '@angular/core';
import { Storage, IonicStorageModule } from '@ionic/storage';
import { Network } from '@capacitor/core';
import { HttpClient } from '@angular/common/http';
import { SharedService } from '../shared/shared.service';
import { DFRPhotoService } from '../dfr/daily-summary/dfr-photo/dfr-photo.service';
import { LoadingController } from '@ionic/angular';
@Injectable({
providedIn: 'root'
})
export class CacheSaveDataService {
status = null;
handler;
loaderElement;
constructor(
public storage: Storage,
private httpClient: HttpClient,
private sharedService: SharedService,
private loadingController: LoadingController) {
this.status = this.getStatus();
if (this.handler === undefined) {
console.log('Add Listener ', status);
this.handler = Network.addListener('networkStatusChange', (status) => {
console.log('Network status changed! ', status);
const oldStatus = this.status;
this.status = status;
if (this.status.connected && !oldStatus.connected) {
this.saveCachedData();
}
this.status = status;
if (!this.status.connected) {
this.sharedService.showNotification('Network connection has terminated.', 'danger', 5000);
}
});
}
}
public async setItem(key, value) {
return await this.storage.set(key, value);
}
public async setStorageRequest2(request) {
const cacheKey = 'reqcache-' + this.sharedService.generateId();
return await this.storage.set(cacheKey, request);
}
public async setStorageRequest(request) {
this.sharedService.showNotification('User is offline. Service Request Cached', 'warning', 2000);
const cacheKey = 'reqcache-' + this.sharedService.generateId() + '-' + request.urlWithParams;
return await this.storage.set(cacheKey, request);
}
public async get(settingName){
return await this.storage.get(`setting:${ settingName }`);
}
public async get2(settingName) {
return await this.storage.get(settingName);
}
public async remove(settingName){
return await this.storage.remove(settingName);
}
public clear() {
this.storage.clear().then(() => {
console.log('all keys cleared');
});
}
public async getKeys() {
return await this.storage.keys();
}
public async getStatus() {
this.status = await Network.getStatus();
}
}
`
// dfr.service.ts (метод только в классе)`
public getDFRByDfrId(id: string) {
return this.httpClient.get(environment.apiURL + this.path + '/id/' + id)
.pipe(
map((res: any) => {
return res.data;
})
);
}
`
// view.ts (только подписка)`
this.dfrService.getDFRByDfrId(paramMap.get('id')).subscribe(val => {
this.currentDFR = val;
});
`
Я ожидаю, что тело моего кэшированного запроса будет возвращено