Angular 创建http请求服务的最佳方法?
我创建了一个服务来处理所有http请求。它工作得很好。但我想知道我的方法是否有任何错误,也想知道其他好的方法,比如observable request.service.jsAngular 创建http请求服务的最佳方法?,angular,typescript,angular-promise,angular5,angular-observable,Angular,Typescript,Angular Promise,Angular5,Angular Observable,我创建了一个服务来处理所有http请求。它工作得很好。但我想知道我的方法是否有任何错误,也想知道其他好的方法,比如observable request.service.js import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import {
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { catchError, map, tap } from 'rxjs/operators';
import { MessageService } from './message.service';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' })
};
interface IRequestOption {
url: string;
cxfgroup: string;
endpoint: string;
data: object;
}
interface IRequestBody {
option: IRequestOption;
log: string;
error: string;
}
class HTTP {
private messageService: MessageService;
constructor(http, messageService, url: string, body: object, log: string, error: string) {
this.callHTTP(http, url, body, log, error);
this.messageService = messageService;
}
callHTTP(http, url, body, log, error) {
return http.post(url, body, httpOptions).toPromise()
.then(this.extractData)
.catch(this.handleErrorPromise);
}
private extractData(res: Response) {
// let body = res.json();
// return body['data'] || {};
return res || {};
}
private handleErrorPromise(error: Response | any) {
console.error(error.message || error);
return Promise.reject(error.message || error);
}
}
class RequestFactory {
private baseURL = 'https://app.domain.com/cxf/';
/**
* CXF ENPOINTS
*/
private endpoints: any = {
"auth": {
"getcustomerkeys": "auth/getcustomerkeys"
}
};
call(http, messageService, options: IRequestOption, log: string, error: string) {
let url: string = options.url ? options.url : this.baseURL;
if (this.endpoints.hasOwnProperty(options['cxfgroup'])) {
url += this.endpoints[options.cxfgroup][options.endpoint];
}
return new HTTP(http, messageService, url, options.data, log, error);
}
}
@Injectable()
export class RequestService {
constructor(private http: HttpClient, private messageService: MessageService) { }
post(request: IRequestBody) {
let requestFactory = new RequestFactory();
requestFactory.call(this.http, this.messageService, request.option, request.log, request.error);
}
}
我使用以下代码调用这个“post”方法。这是我想要的
为了在请求完成后设定承诺,我想展示一些
信息
抱歉,Libu,它比您的代码更“简单”。您不需要创建类、类和类。此外,最好的方法是总是返回一个可观察的。实际上,用承诺代替可观察是没有好处的。如果您返回一个可观察对象,您可以“链”(使用开关映射)、“组”(使用fork)等
HTTP服务 以下是我们在项目中使用的基于观察的方法:
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class HttpService {
constructor(private http: HttpClient) {}
/**
* Invoke function should be able to handle any HTTP request based on the @params
*/
invoke(params): Observable<any> {
if (params) {
const method = params.method.toLowerCase();
const { url, path, body, headers, query } = params;
const requestURL = `${url}/${path}`;
let request;
let requestParams = new HttpParams();
let requestHeaders = new HttpHeaders();
/**
* DEFAULT HEADERS
*/
requestHeaders = requestHeaders.set('Content-Type', 'application/json');
/**
* CUSTOM HEADERS
*/
if (headers) {
for (const key in headers) {
if (headers.hasOwnProperty(key)) {
requestHeaders = requestHeaders.append(key, headers[key]);
}
}
}
/**
* CUSTOM REQUEST QUERY (?key=value)
*/
if (query) {
for (const key in query) {
if (query.hasOwnProperty(key)) {
requestParams = requestParams.append(key, query[key]);
}
}
}
const requestOptions = {
headers: requestHeaders,
params: requestParams,
};
/**
* HANDLE GET, POST etc. REQUESTS
*/
if (method === 'get') {
request = this.http[method](requestURL, requestOptions);
} else if (method === 'post' || method === 'put') {
request = this.http[method](
requestURL,
JSON.stringify(body),
requestOptions,
);
} else if (method === 'delete') {
request = this.http.request(method, requestURL, {
...requestOptions,
body: JSON.stringify(body),
});
} else {
console.error('Unknown request method.');
}
/**
* RETURN API REQUEST
*/
return request;
}
}
}
请注意,正文
、标题
和查询
是可选的
组件中的使用示例
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { catchError, map, tap } from 'rxjs/operators';
import { MessageService } from './message.service';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' })
};
interface IRequestOption {
url: string;
cxfgroup: string;
endpoint: string;
data: object;
}
interface IRequestBody {
option: IRequestOption;
log: string;
error: string;
}
class HTTP {
private messageService: MessageService;
constructor(http, messageService, url: string, body: object, log: string, error: string) {
this.callHTTP(http, url, body, log, error);
this.messageService = messageService;
}
callHTTP(http, url, body, log, error) {
return http.post(url, body, httpOptions).toPromise()
.then(this.extractData)
.catch(this.handleErrorPromise);
}
private extractData(res: Response) {
// let body = res.json();
// return body['data'] || {};
return res || {};
}
private handleErrorPromise(error: Response | any) {
console.error(error.message || error);
return Promise.reject(error.message || error);
}
}
class RequestFactory {
private baseURL = 'https://app.domain.com/cxf/';
/**
* CXF ENPOINTS
*/
private endpoints: any = {
"auth": {
"getcustomerkeys": "auth/getcustomerkeys"
}
};
call(http, messageService, options: IRequestOption, log: string, error: string) {
let url: string = options.url ? options.url : this.baseURL;
if (this.endpoints.hasOwnProperty(options['cxfgroup'])) {
url += this.endpoints[options.cxfgroup][options.endpoint];
}
return new HTTP(http, messageService, url, options.data, log, error);
}
}
@Injectable()
export class RequestService {
constructor(private http: HttpClient, private messageService: MessageService) { }
post(request: IRequestBody) {
let requestFactory = new RequestFactory();
requestFactory.call(this.http, this.messageService, request.option, request.log, request.error);
}
}
最后,您需要订阅组件中的一个可观察项以发出请求:
this.yourServiceName.makeRequest().subscribe(
success => {
// handle success
},
error => {
// handle error
}
);
错误处理
为了处理我们可以使用的错误,它看起来像这样:
constructor(private http: HttpService) {}
makeRequest() {
return this.http.invoke({
method: 'POST', // method like POST, GET etc.
url: 'http://blabla', // base URL
path: 'makeReq', // API endpoint
body: ..., // body for POST or PUT requests
headers: {headerName: 'HeaderValue'} // headers you need to add to your request
query: {query: 'queryValue'} // URL query to be added (eg. ?query=queryValue)
});
}
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';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler,
): Observable<HttpEvent<any>> {
return next.handle(req).catch(errorReponse => {
let error: string;
if (errorReponse instanceof HttpErrorResponse) {
error = errorReponse.error;
const { status, statusText, message } = errorReponse;
const errMsg = `HTTP ERROR: ${status} - ${statusText}\n${message}\n\nBACKEND RESPONSE: `;
console.error(errMsg, error);
} else {
error = null;
}
return _throw(error);
});
}
}
export const ErrorHttpInterceptor = {
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true,
};
类似的方法可用于注入
授权
令牌等。请看一下,感谢您的回复。对不起,但是我有不同的方法,比如发帖,获取等等。。所以无论如何,我需要分离代码。@Libu Mathew,在你的代码中,我看不到不同的方法:(是的。但我需要所有这些方法。这就是我分离代码的原因。你可以在服务中提出“请求”而不是“发布”或添加“获取”方法。是的,我这样做了。
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';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler,
): Observable<HttpEvent<any>> {
return next.handle(req).catch(errorReponse => {
let error: string;
if (errorReponse instanceof HttpErrorResponse) {
error = errorReponse.error;
const { status, statusText, message } = errorReponse;
const errMsg = `HTTP ERROR: ${status} - ${statusText}\n${message}\n\nBACKEND RESPONSE: `;
console.error(errMsg, error);
} else {
error = null;
}
return _throw(error);
});
}
}
export const ErrorHttpInterceptor = {
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true,
};
@NgModule({
providers: [ErrorHttpInterceptor]
})