Angular 创建http请求服务的最佳方法?

Angular 创建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 {

我创建了一个服务来处理所有http请求。它工作得很好。但我想知道我的方法是否有任何错误,也想知道其他好的方法,比如observable

request.service.js

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]
})