首页 > 解决方案 > 在 Angular 6 中创建通用 Http 服务包装器好不好

问题描述

我创建了一个通用的 http 服务包装器,并将它注入到每个组件中。我有点困惑的是,

是在每个组件中注入 HttpClient 服务还是像我创建的那样创建一个 http 服务包装器更好?

或者我们可以两者都做?

请对此提出一些建议。这将非常有帮助。

import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../../../environments/environment';
import { LoaderService } from './loader.service';
import { FormUtils } from '../utils/form.utils';

@Injectable({
  providedIn: 'root'
})
export class HttpService {
  private apiUrl: string;

  constructor(private http: HttpClient, private _loaderService: LoaderService) {
    this.apiUrl = environment.url;
  }

  post<T>(url, data, loader = true): Observable<Common.ApiResponse<T>> {
    if (loader) {
      this._loaderService.loader.next(loader);
    }
    return this.http.post<Common.ApiResponse<T>>(this.apiUrl + url, data);
  }

  put<T>(url, data, loader = true): Observable<Common.ApiResponse<T>> {
    if (loader) {
      this._loaderService.loader.next(loader);
    }
    return this.http.put<Common.ApiResponse<T>>(this.apiUrl + url, data);
  }

  patch<T>(url, data, loader = true): Observable<Common.ApiResponse<T>> {
    if (loader) {
      this._loaderService.loader.next(loader);
    }
    return this.http.patch<Common.ApiResponse<T>>(this.apiUrl + url, data);
  }

  get<T>(
    url,
    httpParams?: any,
    loader = true
  ): Observable<Common.ApiResponse<T>> {
    const updatedParams = this.parseDateToTimeStamp(httpParams);
    console.log(updatedParams, '--------------');

    if (loader) {
      this._loaderService.loader.next(loader);
    }
    for (let item in httpParams) {
      if (
        httpParams[item] === '' ||
        httpParams[item] === undefined ||
        httpParams[item] === null
      ) {
        delete httpParams[item];
      }
    }
    const header = {};
    if (httpParams) {
      header['params'] = updatedParams;
    }
    return this.http.get<Common.ApiResponse<T>>(this.apiUrl + url, header);
  }

  parseDateToTimeStamp(obj: any) {
    const newValueInstance = Object.assign({}, obj);
    (function isEmpty(data: any): boolean {
      if (typeof data === 'object' && data !== null) {
        if (Array.isArray(data)) {
          data.forEach((item: any, index: number) => {
            if (isEmpty(item)) {
              data.splice(index, 1);
            }
          });
        } else {
          Object.keys(data).map((key, index) => {
            console.log(data[key] instanceof Date);
            if (data[key] instanceof Date) {
              data[key] = new Date(data[key]).getTime();
            }
          });
        }
      }
      return data;
    })(newValueInstance);
    return newValueInstance;
  }
}

标签: angular

解决方案


除非您知道自己在做什么,否则我真的不建议您这样做...

此外,如果您只是为加载器服务创建此包装器服务。考虑改用角度拦截器。拦截器将检测何时发出 http 请求并显示您的加载程序。阅读这篇中等文章/指南:Angular 6 中每个 HTTP 请求的加载器栏

目前,您的“包装器”仅允许将 url 链接、HttpParams、正文和加载器变量作为参数传入。当您必须集成需要特定HttpHeaders设置或具有不同responseType(如“文本”)的其他 API 端点时,您将开始面临问题。您最终不得不一次又一次地修改您的包装服务,并且浪费大量时间来保存几行代码。

或者您可能只是尝试做一个简单的 get 请求而不想调用parseDateToTimeStamp(). 你不能用你的wrapper service做到这一点。

或者,如果您想HEAD提出请求,那么您最终将不得不修改您的包装服务,或者在您的应用程序中混合使用包装服务和原始HttpClient包,这只是代码异味。

你最好直接使用 HttpClient 包。

相反,您可以创建一个新的 .ts 文件,可能将其命名为DateTimeHelper.ts或其他名称,然后将其导出parseDateToTimeStamp(),如下所示:

export function parseDateToTimeStamp(){}

然后将此功能导入您需要使用的任何服务功能中。

在这样做时,您还需要将代码的以下部分抽象为一个单独的函数(类似这样):

export function updateMyParams(httpParams: HttpParams){ //or some identifier that you prefer
    const updatedParams = this.parseDateToTimeStamp(httpParams);
    console.log(updatedParams, '--------------');

    if (loader) {
      this._loaderService.loader.next(loader);
    }
    for (let item in httpParams) {
      if (
        httpParams[item] === '' ||
        httpParams[item] === undefined ||
        httpParams[item] === null
      ) {
        delete httpParams[item];
      }
    }
    const header = {};
    if (httpParams) {
      header['params'] = updatedParams;
    }
}

您只需要为您需要使用它的服务重新导入这两个功能。


推荐阅读