반응형
이제 droughError(오류)는 사용되지 않지만 새로운 오류(HttpErrorResponse)는 없다.
보아하니throwError(error)
지금은 더 이상 사용되지 않는다.VS Code의 IntelliSense는throwError(() => new Error('error')
.new Error(...)
현악만 받아들이다내 것을 깨뜨리지 않고 교체할 수 있는 올바른 방법은 무엇일까?HttpErrorHandlerService
?
http-htp.properties.ts
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse,
HttpResponse,
HttpHeaders
} from '@angular/common/http';
import { Observable, EMPTY, finalize, catchError, timeout, map, throwError } from 'rxjs';
import { HttpErrorHandlerService } from '@core/services';
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
private readonly APP_XHR_TIMEOUT = 6000;
constructor(private errorHandlerService: HttpErrorHandlerService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(this.performRequest(request)).pipe(
timeout(this.APP_XHR_TIMEOUT),
map((event: HttpEvent<any>) => this.handleSuccessfulResponse(event)),
catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next)),
finalize(this.handleRequestCompleted.bind(this))
);
}
private performRequest(request: HttpRequest<any>): HttpRequest<any> {
let headers: HttpHeaders = request.headers;
//headers = headers.set('MyCustomHeaderKey', `MyCustomHeaderValue`);
return request.clone({ headers });
}
private handleSuccessfulResponse(event: HttpEvent<any>): HttpEvent<any> {
if (event instanceof HttpResponse) {
event = event.clone({ body: event.body.response });
}
return event;
}
private processRequestError(
error: HttpErrorResponse,
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
console.log('http error response');
if ([401].includes(error.status)) {
return throwError(error);
}
this.errorHandlerService.handle(error);
return throwError(error);
}
private handleRequestCompleted(): void {
// console.log(`Request finished`);
}
}
import { Injectable } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { MessageService } from 'primeng/api';
import { TimeoutError } from 'rxjs';
/**
* Shows a user-friendly error message when a HTTP request fails.
*/
@Injectable({
providedIn: 'root'
})
export class HttpErrorHandlerService {
constructor(private messageService: MessageService) {}
handle(error: Error | HttpErrorResponse) {
if (error instanceof TimeoutError) {
return this.openDialog('error', `Няма връзка до сървъра.`);
}
if (error instanceof HttpErrorResponse && error.error && error.error.message) {
return this.openDialog('error', error.error.message);
}
if (error instanceof Error) {
switch (error.message) {
default:
return this.openDialog('error', `An unknown error occurred`);
}
}
// Generic HTTP errors
switch (error.status) {
case 400:
switch (error.error) {
case 'invalid_username_or_password':
return this.openDialog('error', 'Невалидно потребителско име или парола');
default:
return this.openDialog('error', 'Bad request');
}
case 401:
return this.openDialog('error', 'Ще трябва да се логнете отново');
case 403:
return this.openDialog('error', `You don't have the required permissions`);
case 404:
return this.openDialog('error', 'Resource not found');
case 422:
return this.openDialog('error', 'Invalid data provided');
case 500:
case 501:
case 502:
case 503:
return this.openDialog('error', 'An internal server error occurred');
case -1:
return this.openDialog(
'error',
'You appear to be offline. Please check your internet connection and try again.'
);
case 0:
return this.openDialog('error', `CORS issue?`);
default:
return this.openDialog('error', `An unknown error occurred`);
}
}
private openDialog(severity: string, message: string) {
if (message?.trim()) {
this.messageService.add({
key: 'interceptor',
severity: severity,
summary: 'Информация',
detail: message,
life: 3000
});
}
}
}
auth.properties.ts
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpErrorResponse
} from '@angular/common/http';
import {
BehaviorSubject,
catchError,
EMPTY,
filter,
finalize,
Observable,
switchMap,
take,
throwError
} from 'rxjs';
import { AuthService } from '@core/services';
import { AuthResponse } from '@core/types';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private refreshTokenInProgress: boolean;
private refreshToken$ = new BehaviorSubject<AuthResponse | null>(null);
constructor(private authService: AuthService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next
.handle(this.performRequest(request))
.pipe(
catchError((error: HttpErrorResponse) => this.processRequestError(error, request, next))
);
}
private performRequest(request: HttpRequest<any>): HttpRequest<any> {
const accessToken = this.authService.getAccessToken();
let headers = request.headers;
if (accessToken) {
headers = headers.set('Authorization', `Bearer ${accessToken}`);
}
return request.clone({ headers });
}
private processRequestError(
error: HttpErrorResponse,
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
console.log('auth interceptor called');
if (
error instanceof HttpErrorResponse &&
error.status === 401 &&
this.authService.isSignedIn()
) {
return this.refreshToken(request, next);
}
return throwError(error);
}
private refreshToken(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('refresh token in auth.interceptor called');
// in case the page consists of more than one requests
if (!this.refreshTokenInProgress) {
this.refreshToken$.next(null);
this.refreshTokenInProgress = true;
return this.authService.refreshToken().pipe(
switchMap((response) => {
if (response) {
this.refreshToken$.next(response);
return next.handle(this.performRequest(request));
}
this.authService.signOut();
return throwError(() => new Error("RefreshTokenFailed"));
}),
catchError((error) => {
this.authService.signOut();
return throwError(error);
}),
finalize(() => (this.refreshTokenInProgress = false))
);
} else {
// wait while getting new token
return this.refreshToken$.pipe(
filter((result) => result !== null),
take(1),
switchMap(() => next.handle(this.performRequest(request)))
);
}
}
}
대신 다음과 같이 하십시오.
catchError((error) => {
this.authService.signOut();
return throwError(error);
}),
이것을 시도해 볼 수 있다.
catchError((error) => {
this.authService.signOut();
return throwError(() => error);
}),
철저하게 테스트할 수는 없었지만 간단한 시도는 효과가 있는 것 같았다.
이것은 간단한 테스트였습니다(RxJS v7.2 사용):
서비스
getProducts(): Observable<IProduct[]> {
return this.http.get<IProduct[]>(this.productUrl)
.pipe(
tap(data => console.log('All: ', JSON.stringify(data))),
catchError(this.handleError)
);
}
private handleError(err: HttpErrorResponse): Observable<never> {
// just a test ... more could would go here
return throwError(() => err);
}
에 유의하십시오.err
여기는 유형이다.HttpErrorResponse
.
구성 요소
ngOnInit(): void {
this.sub = this.productService.getProducts().subscribe({
next: products => {
this.products = products;
this.filteredProducts = this.products;
},
error: err => this.errorMessage = err.message
});
}
여기서 나는 그 물건을 되찾을 수 있었다.message
오류 응답의 속성 및 UI에 표시.
이것이 너에게 효과가 있는지 내게 알려줘.
간단히 사용:
return new Error(message);
불필요한 사용
return throwError(() => new Error(message));
반응형
'Programing' 카테고리의 다른 글
Vuetify에서 사용자 지정 테마를 사용하고 색 변수를 구성 요소에 전달 (0) | 2022.03.29 |
---|---|
리액션 후크에 있는 많은 소스에서 가져온 경우 리액션을 방지하는 방법 (0) | 2022.03.29 |
Vuex에서 이 JS 어레이를 줄이지 않는 이유 (0) | 2022.03.29 |
경고:마운트 해제된 구성 요소에 대해 반응 상태 업데이트를 수행할 수 없음 (0) | 2022.03.29 |
ActivitySubject에 가입했을 때 관찰 가능한 약속을 두 번 실행하지 않는 방법 (0) | 2022.03.29 |