В моем текущем проекте я использую Adal.js с угловым 5 для обработки аутентификации.
Но сейчас у меня довольно странная проблема с http-перехватчиком и данными ответа.
Основная логика моего перехватчика заключается в том, что я попытаюсь выполнить вызов API с помощью кэшированного токена, если произойдет сбой с 401, я получу новый токен и попытаюсь повторить вызов с новым токеном.
Но то, что происходит после второго вызова, мое представление не будет обновлять с какими-либо полученными данными, если я не взаимодействую со страницей каким-либо образом. (щелчок, прокрутка и т. д.)
Любая идея, что может вызвать это и в любом случае это исправить?
1012 * редактировать *
Я только что узнал, что могу внедрить ChangeDetectorRef и обнаружить изменения, которые заставят представление визуализироваться. Мне не понравится это решение, потому что оно будет означать, что каждый вызов API требует обнаружения изменений, что звучит как плохая идея. Есть ли более элегантные решения?
компонент
import { Component, OnInit, Injector } from '@angular/core';
import { AppBaseComponent } from '../../../../global/app-base.component';
import { VendorVM } from "../../../../proxy/service-proxies";
import { VendorsService } from '../vendors.service';
@Component({
selector: 'vendors-list',
templateUrl: './vendors.list.component.html',
styleUrls: []
})
export class VendorsListComponent extends AppBaseComponent implements OnInit {
public vendors: VendorVM[];
constructor(
injector: Injector,
public service: VendorsService) {
super(injector);
}
ngOnInit(): void {
this.getVendors();
}
public getVendors() {
this.service.getVendorsForList().subscribe(data => {
this.vendors = data;
this.vendorsUnfiltered = data;
console.log('vendors loaded');
console.log(this.vendors);
});
}
}
перехватчик
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpEvent, HttpResponse, HttpErrorResponse, HttpRequest } from '@angular/common/http';
import { AuthService } from '../global/services/auth.service';
import { Observable } from 'rxjs/Observable';
import { AdalService } from './../global/services/adal.service';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private _auth: AuthService, private adal: AdalService) { }
addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
return request = request.clone({
setHeaders: {
Authorization: 'Bearer ' + token
}
});
}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const authReq = this.addToken(request, this._auth.getToken());
return next.handle(authReq)
.map((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
return event;
}
})
.catch((err: any) => {
console.log('http error');
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
console.log('401 get new token');
return this.adal
.getNewToken()
.flatMap((res) => {
console.log(res);
return next.handle(this.addToken(request, res))
});
} else if (err.status === 403) {
console.log('403', err);
}
} else {
console.log('unknown error', err);
return Observable.throw(err);
}
})
}
}
Просто чтобы повторить, происходят следующие две вещи.
вызов компонента -> перехватчик -> получить кешированный токен -> авторизацию и выполнить вызов -> успех загружает данные и отображает представление.
вызов компонента -> перехватчик -> получить кешированный токен -> авторизация и выполнить вызов -> 401 аутентификационный токен с ошибкой истек -> получить новый токен -> авторизацию и выполнить вызов с новым токеном -> успех загружает данные, но представление не отображает .