处理后端服务器错误的可观察转换
Observable transformation to handle backend server error
抱歉 newbie/dump 关于 RxJS 的问题,刚开始学习 Angular。
所以我创建了一个异步验证器静态方法,它调用一个 API 服务方法来检查数据库中用户名的唯一性。下面的代码片段在后端服务器启动且 运行 时有效。如果不是,它会打印一条错误日志消息,我应该在演示组件中处理它。
在处理此类泛型用例以将 Observable<SuccessResponse>
和 Observable<ErrorResponse>
转换为 Observable<ValidationErrors | null>
的转换步骤中缺少什么。
验证者
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return service.isUsernameTaken(control.value as string)
.pipe(
map((response: SuccessResponse) => response.data ? { taken: true } : null)
);
};
}
ApiService
isUsernameTaken(username: string): Observable<SuccessResponse | ErrorResponse> {
return this.httpCient.get('/backend/account/checkUnique', { params: { username: username } })
.pipe(catchError(this.handleError));
}
handleError(error: HttpErrorResponse) : Observable<ErrorResponse> {
// return specific payload of ErrorResponse based on error.status
}
提前致谢。
我不确定您 运行 遇到了什么问题。如果您尝试将映射解析为验证器内的 ValidationErrors,则需要检查类型。在此示例中,我返回一个名为 "apiError" 的错误以区别于 "taken" 错误,但我不确定您选择如何在您的应用程序中处理这种情况。
我假设 ErrorResponse
包含一个 error
字段,并且 SuccessResponse
包含一个 data
字段。
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return this.isUsernameTaken(control.value as string)
.pipe(
map(response => {
if ('error' in response) { // response is ErrorResponse
return { apiError: response.error };
}
return response.data ? { taken: true } : null;
})
);
};
如果您使用 new ErrorResponse()
和 new SuccessResponse()
构建实际的 class 实例,您可以使用 intanceof
而不是使用 in
运算符检查字段。例如if (response instanceof ErrorResponse)
.
或者,您可以将错误冒泡回验证器,并在另一个 catchError
中处理响应。我更喜欢这种方式,因为 api.
的响应没有条件逻辑
验证器
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return this.isUsernameTaken(control.value as string)
.pipe(
map(response => response.data ? { taken: true } : null),
catchError((err: ErrorResponse) => of({ apiError: err.error }))
);
};
}
ApiService
isUsernameTaken(username: string): Observable<SuccessResponse> {
return this.http.get('/backend/account/checkUnique', { params: { username } })
.pipe(
map(response => response as SuccessResponse), // maps the api response to SuccessResponse
catchError(this.handleError) // maps the error to ErrorResponse
);
}
handleError(error: HttpErrorResponse): Observable<never> {
let errorResponse: ErrorResponse;
// specific payload of ErrorResponse based on error.status
return throwError(errorResponse);
}
抱歉 newbie/dump 关于 RxJS 的问题,刚开始学习 Angular。
所以我创建了一个异步验证器静态方法,它调用一个 API 服务方法来检查数据库中用户名的唯一性。下面的代码片段在后端服务器启动且 运行 时有效。如果不是,它会打印一条错误日志消息,我应该在演示组件中处理它。
在处理此类泛型用例以将 Observable<SuccessResponse>
和 Observable<ErrorResponse>
转换为 Observable<ValidationErrors | null>
的转换步骤中缺少什么。
验证者
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return service.isUsernameTaken(control.value as string)
.pipe(
map((response: SuccessResponse) => response.data ? { taken: true } : null)
);
};
}
ApiService
isUsernameTaken(username: string): Observable<SuccessResponse | ErrorResponse> {
return this.httpCient.get('/backend/account/checkUnique', { params: { username: username } })
.pipe(catchError(this.handleError));
}
handleError(error: HttpErrorResponse) : Observable<ErrorResponse> {
// return specific payload of ErrorResponse based on error.status
}
提前致谢。
我不确定您 运行 遇到了什么问题。如果您尝试将映射解析为验证器内的 ValidationErrors,则需要检查类型。在此示例中,我返回一个名为 "apiError" 的错误以区别于 "taken" 错误,但我不确定您选择如何在您的应用程序中处理这种情况。
我假设 ErrorResponse
包含一个 error
字段,并且 SuccessResponse
包含一个 data
字段。
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return this.isUsernameTaken(control.value as string)
.pipe(
map(response => {
if ('error' in response) { // response is ErrorResponse
return { apiError: response.error };
}
return response.data ? { taken: true } : null;
})
);
};
如果您使用 new ErrorResponse()
和 new SuccessResponse()
构建实际的 class 实例,您可以使用 intanceof
而不是使用 in
运算符检查字段。例如if (response instanceof ErrorResponse)
.
或者,您可以将错误冒泡回验证器,并在另一个 catchError
中处理响应。我更喜欢这种方式,因为 api.
验证器
static usernameUnique(service: ApiService): AsyncValidatorFn {
return (control: FormControl): Observable<ValidationErrors | null> => {
return this.isUsernameTaken(control.value as string)
.pipe(
map(response => response.data ? { taken: true } : null),
catchError((err: ErrorResponse) => of({ apiError: err.error }))
);
};
}
ApiService
isUsernameTaken(username: string): Observable<SuccessResponse> {
return this.http.get('/backend/account/checkUnique', { params: { username } })
.pipe(
map(response => response as SuccessResponse), // maps the api response to SuccessResponse
catchError(this.handleError) // maps the error to ErrorResponse
);
}
handleError(error: HttpErrorResponse): Observable<never> {
let errorResponse: ErrorResponse;
// specific payload of ErrorResponse based on error.status
return throwError(errorResponse);
}