我的数据服务如下所示:
@Injectable()
export class DataService {
baseUrl = 'http://localhost'
constructor(
private httpClient: HttpClient) {
}
get(url, params): Promise<Object> {
return this.sendRequest(this.baseUrl + url, 'get', null, params)
.map((res) => {
return res as Object
})
.toPromise();
}
post(url, body): Promise<Object> {
return this.sendRequest(this.baseUrl + url, 'post', body)
.map((res) => {
return res as Object
})
.toPromise();
}
patch(url, body): Promise<Object> {
return this.sendRequest(this.baseUrl + url, 'patch', body)
.map((res) => {
return res as Object
})
.toPromise();
}
sendRequest(url, type, body, params = null): Observable<any> {
return this.httpClient[type](url, { params: params }, body)
}
}
如果我得到一个HTTP错误(即404),我会从core得到一条令人讨厌的控制台消息:error error:Uncaught(promise):[object]。es5。在我的情况下,我该如何处理?
随着HTTPClient
API的到来,不仅替换了Http
API,还添加了一个新的API,即HttpInterceptor
API。
AFAIK的目标之一是向所有HTTP传出请求和传入响应添加默认行为。
因此,假设您想要添加默认的错误处理行为,将. cat()
添加到所有可能的http.get/post/etc方法中是非常难以维护的。
例如,可以使用HttpInterceptor
,通过以下方式完成此操作:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { _throw } from 'rxjs/observable/throw';
import 'rxjs/add/operator/catch';
/**
* Intercepts the HTTP responses, and in case that an error/exception is thrown, handles it
* and extract the relevant information of it.
*/
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
/**
* Intercepts an outgoing HTTP request, executes it and handles any error that could be triggered in execution.
* @see HttpInterceptor
* @param req the outgoing HTTP request
* @param next a HTTP request handler
*/
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req)
.catch(errorResponse => {
let errMsg: string;
if (errorResponse instanceof HttpErrorResponse) {
const err = errorResponse.message || JSON.stringify(errorResponse.error);
errMsg = `${errorResponse.status} - ${errorResponse.statusText || ''} Details: ${err}`;
} else {
errMsg = errorResponse.message ? errorResponse.message : errorResponse.toString();
}
return _throw(errMsg);
});
}
}
/**
* Provider POJO for the interceptor
*/
export const ErrorInterceptorProvider = {
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true,
};
//app.module.ts
import { ErrorInterceptorProvider } from 'somewhere/in/your/src/folder';
@NgModule({
...
providers: [
...
ErrorInterceptorProvider,
....
],
...
})
export class AppModule {}
OP的一些额外信息:调用http。没有强类型的get/post/etc不是API的最佳使用。您的服务应如下所示:
// These interfaces could be somewhere else in your src folder, not necessarily in your service file
export interface FooPost {
// Define the form of the object in JSON format that your
// expect from the backend on post
}
export interface FooPatch {
// Define the form of the object in JSON format that your
// expect from the backend on patch
}
export interface FooGet {
// Define the form of the object in JSON format that your
// expect from the backend on get
}
@Injectable()
export class DataService {
baseUrl = 'http://localhost'
constructor(
private http: HttpClient) {
}
get(url, params): Observable<FooGet> {
return this.http.get<FooGet>(this.baseUrl + url, params);
}
post(url, body): Observable<FooPost> {
return this.http.post<FooPost>(this.baseUrl + url, body);
}
patch(url, body): Observable<FooPatch> {
return this.http.patch<FooPatch>(this.baseUrl + url, body);
}
}
从您的服务方法返回promise
,而不是可观察的
是另一个错误的决定。
还有一个额外的建议:如果你正在使用TYPEcript,那么开始使用它的类型部分。你失去了语言的最大优势之一:知道你正在处理的值的类型。
在我看来,如果你想要一个角度服务的好例子,看看下面的要点。
请允许我更新acdcjunior关于使用具有最新RxJs功能的HttpInterceptor的回答(第6版)。
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpErrorResponse,
HttpHandler,
HttpEvent,
HttpResponse
} from '@angular/common/http';
import { Observable, EMPTY, throwError, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
catchError((error: HttpErrorResponse) => {
if (error.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${error.status}, body was: ${error.error}`);
}
// If you want to return a new response:
//return of(new HttpResponse({body: [{name: "Default value..."}]}));
// If you want to return the error on the upper level:
//return throwError(error);
// or just return nothing:
return EMPTY;
})
);
}
}
根据你的需要,你有一些选择。如果您希望在每个请求的基础上处理错误,请在请求中添加一个catch
。如果要添加全局解决方案,请使用HttpInterceptor
。
在这里打开下面解决方案的工作演示插件。
在最简单的情况下,您只需要添加一个. cat()
或一个.订阅()
,例如:
import 'rxjs/add/operator/catch'; // don't forget this, or you'll get a runtime error
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});
// or
this.httpClient
.get("data-url")
.subscribe(
data => console.log('success', data),
error => console.log('oops', error)
);
但还有更多细节,见下文。
如果只需要在一个位置处理错误,可以使用catch
并返回默认值(或空响应),而不是完全失败。您也不需要。映射
仅为了强制转换,您可以使用通用函数。资料来源:Angular。io-获取错误详细信息。
因此,一个通用的。get()
方法,类似于:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class DataService {
baseUrl = 'http://localhost';
constructor(private httpClient: HttpClient) { }
// notice the <T>, making the method generic
get<T>(url, params): Observable<T> {
return this.httpClient
.get<T>(this.baseUrl + url, {params})
.retry(3) // optionally add the retry
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value
// return Observable.of<any>({my: "default value..."});
// or simply an empty observable
return Observable.empty<T>();
});
}
}
处理此错误将允许您的应用程序继续运行,即使URL上的服务状况不佳。
当您希望向每个方法返回特定的默认响应时,这种按请求解决方案非常好。但是如果你只关心错误显示(或者有一个全局默认响应),更好的解决方案是使用拦截器,如下所述。
在这里运行工作演示柱塞。
再一次,棱角分明。io指南显示:
@角/公共/超文本传输协议
的一个主要特性是拦截,能够声明位于应用程序和后端之间的拦截器。当您的应用程序发出请求时,拦截器会在将其发送到html" target="_blank">服务器之前对其进行转换,拦截器可以在应用程序看到响应之前在返回的途中对其进行转换。这对于从身份验证到日志记录的一切都很有用。
当然,可以用一种非常简单的方法来处理错误(这里是演示plunker):
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse,
HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value (which has to be a HttpResponse here)
// return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
// or simply an empty observable
return Observable.empty<HttpEvent<any>>();
});
}
}
提供拦截器:简单地声明上面的HttpErrorInterceptor
不会导致您的应用程序使用它。您需要将其作为拦截器提供到您的应用模块中,如下所示:
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpErrorInterceptor } from './path/http-error.interceptor';
@NgModule({
...
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptor,
multi: true,
}],
...
})
export class AppModule {}
注意:如果您同时拥有一个错误拦截器和一些本地错误处理,那么很自然地,很可能不会触发任何本地错误处理,因为错误总是在到达本地错误处理之前由拦截器处理。
在这里运行工作演示柱塞。
问题内容: 我听说捕捞被认为是不好的作法。我当前正在加载一个不能保证在PATH上的.dll,并希望在不存在的情况下切换到用户配置的位置。 有更好的方法吗?还是在这里接受是可以接受的? 问题答案: 除了提供有关如何从技术上解决问题的建议以外,我想花点时间解释一下为什么它首先被认为是“不好的做法”。 让我们从澄清什么是类开始。 在Java中,将引发错误和异常(它们是主要类型)。通过使用关键字可以完成上
我定义了一个自定义错误处理程序,它捕获所有异常并将其保存到日志中。现在,如果我在mysqli查询中出现语法错误,例如打字错误,页面将完全停止加载。没有引发异常,因此不会触发错误处理程序,也不会记录任何内容。 这正常吗?我是否应该检查PHP设置来修复此问题,以便任何mysqli查询错误都会引发异常? (如果查询返回0个结果,我不希望引发异常-仅当它由于键入错误或查询结构中的其他错误而出错时) 查询示
我正在开发一个django应用程序,它可以与几个Amazon Web服务进行通信。 到目前为止,我在处理和捕获boto3客户端抛出的异常方面遇到了困难。我正在做的事情似乎不必要地单调乏味: 例子: 如果令牌坏了,这可能会抛出一个。 可能会抛出一个。 首先,我在代码中的任何地方都找不到这些错误,所以它们可能是在某个地方生成的。一句话:我不能像往常一样导入和捕获它。 其次,我发现了一种方法来捕获错误这
在节点中。在js服务器上,捕获SIGTERM和捕获SIGINT有什么区别吗? 我认为进程不应该能够防止SIGINT关闭? 我是否能够捕获两个信号并阻止退出?我的实验表明答案是肯定的,但从我所读到的内容来看,SIGINT总是假设关闭一个进程。 或者我把SIGINT和SIGKILL混淆了?也许SIGKILL是我无法恢复的信号? 捕捉这些信号当然可以让我优雅地关机: 我想我把SIGINT和SIGKILL
如果 Scala 未来失败,并且没有延续“观察到”该故障(或者唯一的延续使用 map/flatMap 并且在发生故障时不运行),那么错误就不会被发现。我希望至少记录这些错误,以便我可以找到错误。 我使用术语“观察到的错误”,因为在.Net Tasks中,当GC收集Task对象时,有机会捕获“未观察到的任务异常”。同样,使用同步方法,可以记录终止线程的未捕获异常。 在Scala futures中,“
问题内容: 在Java中是否有捕捉到内存不足错误()的问题? 问题答案: 是的 。以下是一些可能有意义的示例: 如果您想通过 优雅地关闭 程序来处理它 如果要向用户显示问题或 记录错误 根据您的设计,您甚至可以清理内存并 恢复工作状态 但是 ,请注意,通常情况下(除非您处在一次要分配大量内存的位置),对于这些情况,您可能不会专门捕获OutOfMemoryError,而是始终在顶部进行操作主要入口点