在 Angular 中调用 httpClient.delete() 时无法处理 HTTP/404 8
Unable to handle HTTP/404 when calling httpClient.delete() in Angular 8
调用 DELETE 方法时,我有 returns HTTP/404 的 Springboot 2.1 端点。
有 Angular 8 个应用程序使用 HttpClient 调用该端点。它已被简化为最简单的代码。
如果我调用 httpClient.delete('url').subscribe(); 而后端 returns HTTP/404 我是无法处理错误。
Angular 在控制台中抛出此错误:错误类型错误:您提供了 'undefined' 预期流的位置。您可以提供 Observable、Promise、Array 或 Iterable。
我尝试按照 Angular http 客户端描述中的描述处理错误,但没有帮助。在调用任何错误处理代码之前,Angular 在控制台中抛出错误并且不执行任何错误处理。
这是Java代码
@RestController
@RequestMapping("/api/test")
@RequiredArgsConstructor
class TestController {
@DeleteMapping("/{id}")
public ResponseEntity deleteObject(@PathVariable("id") Long id) {
return ResponseEntity.notFound().build();
}
}
Angular 调用此端点的代码是:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ObjectsService {
constructor(private httpClient: HttpClient) {
}
deleteObject() {
return this.httpClient.delete('http://localhost:8090/api/test/5').subscribe();
}
}
Chrome 显示响应为:
Request URL: http://localhost:8090/api/test/5
Request Method: DELETE
Status Code: 404
Remote Address: [::1]:8090
Referrer Policy: no-referrer-when-downgrade
不幸的是,我没有正常执行,而是在控制台中收到错误消息:
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:27)
at subscribeToResult (subscribeToResult.js:11)
at CatchSubscriber.error (catchError.js:38)
at XMLHttpRequest.onLoad (http.js:2476)
at ZoneDelegate.invokeTask (zone-evergreen.js:391)
at Object.onInvokeTask (core.js:39679)
at ZoneDelegate.invokeTask (zone-evergreen.js:390)
at Zone.runTask (zone-evergreen.js:168)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:465)
at invokeTask (zone-evergreen.js:1603)
编辑:
还有正在处理错误的 HTTPInterceptor:
private handleErrors(err: HttpErrorResponse): Observable<any> {
if (err.status === 401) {
this.loginService.redirectToUrl = this.router.url;
this.router.navigate(['/login']);
return of(err.message);
}
}
感谢@igor,"missing else" 被发现了。在拦截器中添加 HTTP/404 处理解决了这个问题。
您需要在 subscribe() 中传递参数以作为响应。在你的例子中
deleteObject() {
return this.httpClient.delete('http://localhost:8090/api/test/5').subscribe(response => {
// Here you will handle response
}, (error) => {
// Here you can handle errors
});
}
如果您需要处理来自所有 API 调用的错误,那么使用通用错误处理程序来处理错误将是一个理想的解决方案。
https://angular.io/api/core/ErrorHandler
有关错误处理程序和拦截器的更多详细信息,
what is the difference between error handler and interceptor in angular 2?
如果未到达在可观察对象上执行的错误处理代码,那么您配置了一个 HttpInterceptor
,它在到达此代码之前处理错误。
我想说的一个好的开始是实现拦截器并处理这些错误:
@Injectable()
export class ServiceHttpInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
...........
next.handle(req)
.pipe(tap(event => {
if (event instanceof HttpResponse) {
// doNothing now
}
}))
.pipe(catchError(err => {
if (err instanceof HttpErrorResponse) {
// Handle your 404 here
}
}
}
}
调用 DELETE 方法时,我有 returns HTTP/404 的 Springboot 2.1 端点。 有 Angular 8 个应用程序使用 HttpClient 调用该端点。它已被简化为最简单的代码。
如果我调用 httpClient.delete('url').subscribe(); 而后端 returns HTTP/404 我是无法处理错误。 Angular 在控制台中抛出此错误:错误类型错误:您提供了 'undefined' 预期流的位置。您可以提供 Observable、Promise、Array 或 Iterable。
我尝试按照 Angular http 客户端描述中的描述处理错误,但没有帮助。在调用任何错误处理代码之前,Angular 在控制台中抛出错误并且不执行任何错误处理。
这是Java代码
@RestController
@RequestMapping("/api/test")
@RequiredArgsConstructor
class TestController {
@DeleteMapping("/{id}")
public ResponseEntity deleteObject(@PathVariable("id") Long id) {
return ResponseEntity.notFound().build();
}
}
Angular 调用此端点的代码是:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ObjectsService {
constructor(private httpClient: HttpClient) {
}
deleteObject() {
return this.httpClient.delete('http://localhost:8090/api/test/5').subscribe();
}
}
Chrome 显示响应为:
Request URL: http://localhost:8090/api/test/5
Request Method: DELETE
Status Code: 404
Remote Address: [::1]:8090
Referrer Policy: no-referrer-when-downgrade
不幸的是,我没有正常执行,而是在控制台中收到错误消息:
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:27)
at subscribeToResult (subscribeToResult.js:11)
at CatchSubscriber.error (catchError.js:38)
at XMLHttpRequest.onLoad (http.js:2476)
at ZoneDelegate.invokeTask (zone-evergreen.js:391)
at Object.onInvokeTask (core.js:39679)
at ZoneDelegate.invokeTask (zone-evergreen.js:390)
at Zone.runTask (zone-evergreen.js:168)
at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:465)
at invokeTask (zone-evergreen.js:1603)
编辑: 还有正在处理错误的 HTTPInterceptor:
private handleErrors(err: HttpErrorResponse): Observable<any> {
if (err.status === 401) {
this.loginService.redirectToUrl = this.router.url;
this.router.navigate(['/login']);
return of(err.message);
}
}
感谢@igor,"missing else" 被发现了。在拦截器中添加 HTTP/404 处理解决了这个问题。
您需要在 subscribe() 中传递参数以作为响应。在你的例子中
deleteObject() {
return this.httpClient.delete('http://localhost:8090/api/test/5').subscribe(response => {
// Here you will handle response
}, (error) => {
// Here you can handle errors
});
}
如果您需要处理来自所有 API 调用的错误,那么使用通用错误处理程序来处理错误将是一个理想的解决方案。
https://angular.io/api/core/ErrorHandler
有关错误处理程序和拦截器的更多详细信息,
what is the difference between error handler and interceptor in angular 2?
如果未到达在可观察对象上执行的错误处理代码,那么您配置了一个 HttpInterceptor
,它在到达此代码之前处理错误。
我想说的一个好的开始是实现拦截器并处理这些错误:
@Injectable()
export class ServiceHttpInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
...........
next.handle(req)
.pipe(tap(event => {
if (event instanceof HttpResponse) {
// doNothing now
}
}))
.pipe(catchError(err => {
if (err instanceof HttpErrorResponse) {
// Handle your 404 here
}
}
}
}