angular - 如何解决角度 7 中的最大调用堆栈大小
问题描述
这是它给出的错误,我在调试代码时获得了最大调用堆栈大小。我认为它陷入了无限循环,但我无法修复它。我应该怎么办?..................................................... ..................................................... ..................................................... ..................................................... ..................................................... ................................................@可注入() 导出类 HttpAuthInterceptor 实现 HttpInterceptor {
private autoAppendHeadersDefault = true;
private refreshObservable: Observable<HttpEvent<any>> = null;
private refreshSubsCount = 0;
constructor(
private storageService: StorageService,
private appState: AppService,
private http: HttpClient
) {
this.autoAppendHeadersDefault = this.appState.hoodConfig.HTTP_AUTO_APPEND_HEADERS;
}
intercept(request: HttpRequest<any>, next: HttpHandler, disableTryFix = false): Observable<HttpEvent<any>> {
let assetRequest = false;
if (request.url.startsWith('/assets')) {
assetRequest = true;
}
const newHeaders = {'Cache-Control': 'public, max-age=45',
'Expires': new Date(new Date().getTime() + 45 * 60 * 1000).toLocaleString()
}
;
if (!assetRequest && this.appState.hoodConfig.HTTP_AUTO_APPEND_HEADERS) {
// append aToken || gToken
let token = this.storageService.get('aToken');
if ('undefined' === typeof token || !token) {
token = this.storageService.get('gToken');
}
if ('undefined' !== typeof token && token) {
newHeaders['Authorization'] = `Bearer ${token}`;
} else {
// neither aToken nor gToken are set
if (disableTryFix) {
this.removeAllTokens();
return observableThrowError({error: 'Can\'t reauth: 01'});
}
return this.tryFixAuth(next).pipe(flatMap(
(res: any) => {
this.storageService.set('gToken', res.access_token);
request = request.clone({
setHeaders: newHeaders
});
return this.intercept(request, next, true);
}
));
}
// headers appended to every request
if (!request.headers.get('Content-Type')) {
newHeaders['Content-Type'] = 'application/json';
}
}
this.appState.hoodConfig.HTTP_AUTO_APPEND_HEADERS = this.autoAppendHeadersDefault;
request = request.clone({
setHeaders: newHeaders
});
return next.handle(request).pipe(catchError((err: any, caught: Observable<HttpEvent<any>>) => {
if (!(err instanceof HttpErrorResponse)) {
return caught;
}
const error = err.error;
if (error.status === 401) {
if (disableTryFix) {
this.removeAllTokens();
this.navigateOnAuthFail();
return observableThrowError({error: 'Can\'t reauth: 02'});
}
return this.tryFixAuth(next).pipe(flatMap(
(res: any) => {
--this.refreshSubsCount;
if ('undefined' !== typeof res.refresh_token) {
// got aToken & refresh_token
this.storageService.set('aToken', res.access_token);
this.storageService.set('refresh_token', res.refresh_token);
} else if ('undefined' !== typeof res.access_token) {
// got only gToken
this.storageService.set('gToken', res.access_token);
} else {
console.log('tryFix: nothing useful returned')
// got no aToken, no gToken, no refresh_token
}
// retry request
return this.intercept(request, next, true);
}
));
}
if (disableTryFix && error.status === 400 && error.url.endsWith('oauth/v2/token')) {
if (!environment.production) {
console.log('Invalid refresh token (400)');
}
this.storageService.remove('refresh_token');
this.storageService.remove('aToken');
this.navigateOnAuthFail();
}
if (disableTryFix && error.status === 403) {
const errorObj = error;
// Server requires aToken but gToken was sent
if (errorObj.message == 'Access Denied.') {
if (!environment.production) {
console.log('No token');
}
this.navigateOnAuthFail();
}
}
return observableThrowError(error);
}));
}
private tryFixAuth(next: HttpHandler): Observable<any> {
if (!this.refreshObservable) {
if (!environment.production) {
console.log('Fixing auth');
}
}
if (this.storageService.get('refresh_token')) {
return this.refreshToken(next);
} else if (this.storageService.get('aToken')) {
// no refresh_token, but aToken
// since aToken is dead it's not useful
this.storageService.remove('aToken');
} else {
return this.guestToken();
}
}
private refreshToken(next: HttpHandler): Observable<any> {
if (this.refreshObservable != null && this.refreshSubsCount > 0) {
// if refreshSubsCount == 0 it means observable has worked for all subscribers and contains outdated request
++this.refreshSubsCount;
return this.refreshObservable;
} else if (this.refreshSubsCount <= 0) {
this.refreshObservable = null;
}
const refreshToken = this.storageService.get('refresh_token');
if ('undefined' === typeof refreshToken || !refreshToken || refreshToken == 'undefined') {
this.storageService.remove('refresh_token');
return observableThrowError({error: 'Refresh token is not set'});
}
const headers = new HttpHeaders();
headers.append('Authorization', `Bearer ${this.storageService.get('gToken')}`);
headers.append('Content-Type', 'application/json');
const url = `${this.appState.config.WEBSITE_ENDPOINT}/oauth/v2/token`;
const localData = {
'client_id': this.appState.config.CLIENT_ID,
'client_secret': this.appState.config.CLIENT_SECRET,
'grant_type': 'refresh_token',
'refresh_token': refreshToken
};
this.appState.hoodConfig.HTTP_AUTO_APPEND_HEADERS = false;
this.refreshObservable = this.intercept(
new HttpRequest<any>(
'POST',
url,
localData,
{
headers: headers
}
),
next, true).pipe(
share(),
filter((event: HttpEvent<any>): boolean => event instanceof HttpResponse),
map((event: HttpResponse<any>): any => event.body)
);
++this.refreshSubsCount;
return this.refreshObservable;
}
private guestToken(): Observable<any> {
const url = `${
this.appState.config.WEBSITE_ENDPOINT}/oauth/v2/token?client_id=${
this.appState.config.CLIENT_ID}&client_secret=${
this.appState.config.CLIENT_SECRET}&grant_type=client_credentials`;
this.appState.hoodConfig.HTTP_AUTO_APPEND_HEADERS = false;
return this.http.get<any>(url);
}
private navigateOnAuthFail() {
console.warn('Page is going to be refreshed');
window.location.reload();
}
private removeAllTokens() {
this.storageService.remove('aToken');
this.storageService.remove('gToken');
this.storageService.remove('refresh_token');
}
}
解决方案
推荐阅读
- r - 带有模型约束的 R 中的逐步回归
- amazon-web-services - 使用 appsync 解析器、aws dymaodb 的嵌套查询
- variables - 在 Ansible 剧本中使用嵌套清单列表
- javascript - Javascript async/await 函数 - 添加多个返回
- javascript - 作用域链中的内部函数和参数函数有什么区别?
- android - 如何使用映射文件对 Android 堆栈跟踪进行去混淆处理
- wordpress - 在 WP_Query 中包含子项
- c++ - 我可以强制使用接口类定义特定的构造函数吗?
- node.js - 在所有测试都启动 cypress 后执行任务
- c# - 打印使用 SQL 存储过程的 Crystal 报表时出错