使用Angular构建动态http服务

使用Angular构建动态http服务,angular,ionic-framework,service,Angular,Ionic Framework,Service,我有一个Ionic应用程序,这个应用程序包含一组页面和服务,现在因为我在使用Ionic&Angular,我决定为不同的项目构建可重用的代码 例如,Http服务:在这个服务中,我想集中管理与服务器端通信的代码,以实现可重用的概念,并且更改将集中在一个地方 我的Http.service代码是: export interface RequestOptions { observable?: any; url?:string; method?: string; successCallBac

我有一个Ionic应用程序,这个应用程序包含一组页面和服务,现在因为我在使用Ionic&Angular,我决定为不同的项目构建可重用的代码

例如,Http服务:在这个服务中,我想集中管理与服务器端通信的代码,以实现可重用的概念,并且更改将集中在一个地方

我的Http.service代码是:

export interface RequestOptions {
  observable?: any;
  url?:string;
  method?: string;
  successCallBack?: any;
  notSuccessCallBack?: any;
  useDefaultNotSuccessCallBack?: boolean;
  errorCallBack?: any;
  useDefaultErrorCallBack?: boolean;
  completeCallBack? : any;
  sendToken?: boolean;
  data?: any;
  refresher?:Refresher;
  infinitScroller?: InfiniteScroll;
  loader?: Loading;
}

export interface ForkOptions {
  requests: RequestOptions[];
  useDefaultNotSuccessCallBack?: boolean;
  errorCallBack?: any;
  useDefaultErrorCallBack?: boolean;
  completeCallBack? : any;
  refresher?:Refresher;
  infinitScroller?: InfiniteScroll;
  loader?: Loading;
}

import {Injectable} from "@angular/core";
import {AuthenticationService} from "./authentication.service";
import {Observable} from "rxjs/Observable";
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {AlertController, InfiniteScroll, Loading, Refresher} from "ionic-angular";
import 'rxjs/add/observable/forkJoin';

@Injectable()
export class HttpConnectionService {

  constructor(
    private http: HttpClient,
    private authService: AuthenticationService,
    private alertCtrl: AlertController
  ) {}

  /**
   * @param {ForkOptions} options: an options which contains the list of requests to be forked together.
   * this method will construct an array of observables and handle the response using @responseHandler and @errorHandler methods
   * in this service
   */
  httpRequests( options: ForkOptions) {
    // build the array of observables
    let observables = [
      ...options.requests.map((request) =>  request.observable)
    ];
    // subscribe to these observables
    Observable.forkJoin(observables).subscribe(
      (results) => {
        // handle the response for each of the requests
        for(let i = 0; i < results.length; i++) {
          this.responseHandler(results[i], options.requests[i]);
        }
      }, (error) => {
        // handle the errors
        this.errorHandler(error, options);
      }, () => {
        // execute the complete handler
        this.completeHandler(options);
      }
    );
  }

  /**
   * @param {RequestOptions} requestOptions: contains the options and attributes of the request to be constructed
   * @returns {any} return a ready to subscribe observable
   */
  createObservable(requestOptions: RequestOptions) {
    // switch statement to handle the different types of methods.
    switch(requestOptions.method) {
      // if the case is post or delete method, they would have the same parameters.
      case 'post' : case 'delete' :
        return this.postDelete(requestOptions);
      // if the case is get method, it will be constructed differently
      case 'get':
        return this.get(requestOptions);
    }
  }

  /**
   *
   * @param {RequestOptions} requestOptions: the options and attribute of the request (post or delete)
   * @returns {any}: return the request observable.
   */
  private postDelete(requestOptions: RequestOptions) {
    return this.http[requestOptions.method](requestOptions.url, requestOptions.data);
  }

  /**
   *
   * @param {RequestOptions} requestOptions
   * @returns {Observable<Object>}
   */
  private get(requestOptions: RequestOptions) {
    return this.http.get(requestOptions.url);
  }

  /**
   *
   * @param {RequestOptions} requestOptions identify different attributes of the request.
   */
  httpRequest(requestOptions: RequestOptions) {
    // send the http request and use the method attribute

    // if there is observable sent with request
    let observable = requestOptions.observable;
    if(observable == undefined){
      // if there is no observable, create one
      observable = this.createObservable(requestOptions);
    }
    observable.subscribe(
      (response: any) => {
        // call the response handler
        this.responseHandler(response, requestOptions);
      }, (error) => {
        // call the error handler
        this.errorHandler(error, requestOptions);
      }, () => {
        // call the complete handler
        this.completeHandler(requestOptions);
      }
    );
  }

  private responseHandler(response, requestOptions: RequestOptions) {
    // if the response success, execute the success call back
    if(response.isSuccess) {
      requestOptions.successCallBack(response.result);
      // check if there is infinit scroller and the response is empty, then disable the infinit scroller
      if(requestOptions.infinitScroller && response.result.length == 0) {
        requestOptions.infinitScroller.enable(false);
      }
    }else {
      // if the response is not success, check if the notSuccessCallBack is defined,
      // if notSuccessCallBack is defined, execute it, other wise, execute the default notSuccess callBacl
      if(requestOptions.notSuccessCallBack) {
        // execute the provided not success callBack
        requestOptions.notSuccessCallBack(response);
      }else if(requestOptions.useDefaultNotSuccessCallBack){
        // execute the default not success callBack
        this.defaultNotSuccessResponse(response);
      }
    }
  }

  private errorHandler(error, requestOptions: RequestOptions  | ForkOptions) {
    // check for the provided error callBack.
    if(requestOptions.errorCallBack) {
      // execute the provided callBack
      requestOptions.errorCallBack(error);
    }else if(requestOptions.useDefaultErrorCallBack){
      // if u can default error handler
      this.defaultErrorHandler(error, requestOptions);
    }
  }

  /**
   *
   * @param {RequestOptions | ForkOptions} requestOptions: the requests options which contain completeCallBack.
   */
  private completeHandler(requestOptions: RequestOptions  | ForkOptions) {
    // if there is complete callBack, execute it.
    if(requestOptions.completeCallBack) {
      requestOptions.completeCallBack();
    }
    // turn off the external components after the response is arrived
    // for example: loader, infinit scroller, refreshing
    this.turnOffExternalComponents(requestOptions);
  }

  /**
   * contains the default behavioral for the not success response,
   * it can be terminated if @useNotSuccessResponse = false in the request options.
   * @param response: the response from the server side which contains the error message.
   */
  private defaultNotSuccessResponse(response) {
    // the default behavioral is to display an error message.
    this.alertCtrl.create({
      title: "Error!",
      subTitle: response.message
    }).present();
  }

  /**
   *
   * @param error: the error object
   * @param {RequestOptions} requestOptions: contains attributes about the request
   * used as params to access the external components when turning them off.
   */
  private defaultErrorHandler(error, requestOptions: RequestOptions | RequestOptions | ForkOptions) {
    // turn off the active components.
    this.turnOffExternalComponents(requestOptions);
    // create alert for the client.
    this.alertCtrl.create({
      title: "Error!",
      subTitle: error.message
    }).present();
  }

  /**
   * terminates the view components which are related to the request,
   * @param {RequestOptions | ForkOptions} requestOptions
   */
  private turnOffExternalComponents(requestOptions: RequestOptions  | ForkOptions) {
    // set the refresher to complete
    if(requestOptions.refresher) {
      requestOptions.refresher.complete();
      // after refreshing, enable the infinit scroller.
      if (requestOptions.infinitScroller) {
        requestOptions.infinitScroller.enable(true);
      }
    }
    // set the infinit Scroller to complete.
    // and turn on the infinit scroller.
    if(requestOptions.infinitScroller) {
      requestOptions.infinitScroller.complete();
    }

    // check if there is loader, and turn it off.
    if(requestOptions.loader) {
      requestOptions.loader.dismissAll();
    }
  }
}
导出接口请求选项{
可观察?:任何;
url?:字符串;
方法?:字符串;
成功回调?:任何;
notSuccessCallBack?:任何;
useDefaultNotSuccessCallBack?:布尔值;
错误回调?:任何;
useDefaultErrorCallBack?:布尔值;
completeCallBack?:任何;
sendToken?:布尔值;
数据?:任何;
复习者?:复习者;
无限卷轴?:无限卷轴;
装载机?:装载;
}
导出接口选项{
请求:请求选项[];
useDefaultNotSuccessCallBack?:布尔值;
错误回调?:任何;
useDefaultErrorCallBack?:布尔值;
completeCallBack?:任何;
复习者?:复习者;
无限卷轴?:无限卷轴;
装载机?:装载;
}
从“@angular/core”导入{Injectable}”;
从“/authentication.service”导入{AuthenticationService};
从“rxjs/Observable”导入{Observable};
从“@angular/common/http”导入{HttpClient,HttpHeaders};
从“离子角度”导入{AlertController,InfiniteScroll,Loading,Refresher};
导入“rxjs/add/observable/forkJoin”;
@可注射()
导出类HttpConnectionService{
建造师(
私有http:HttpClient,
私有authService:AuthenticationService,
私有alertCtrl:AlertController
) {}
/**
*@param{ForkOptions}options:一个包含要分叉在一起的请求列表的选项。
*此方法将构造一个观察值数组,并使用@responseHandler和@errorHandler方法处理响应
*在这项服务中
*/
httpRequests(选项:ForkOptions){
//构建可观察的数组
设可观测项=[
…options.requests.map((请求)=>request.observable)
];
//同意这些观察结果
可观察的。forkJoin(可观察的)。订阅(
(结果)=>{
//处理每个请求的响应
for(设i=0;i{
//处理错误
this.errorHandler(错误,选项);
}, () => {
//执行完整的处理程序
this.completeHandler(选项);
}
);
}
/**
*@param{RequestOptions}RequestOptions:包含要构造的请求的选项和属性
*@returns{any}返回准备订阅的可观察
*/
createObservable(请求选项:请求选项){
//switch语句来处理不同类型的方法。
开关(requestOptions.method){
//如果案例是post或delete方法,则它们将具有相同的参数。
案例“发布”:案例“删除”:
返回此.postDelete(requestOptions);
//如果案例是get方法,那么它将以不同的方式构造
案例“get”:
返回此.get(requestOptions);
}
}
/**
*
*@param{RequestOptions}RequestOptions:请求的选项和属性(post或delete)
*@returns{any}:返回可观察的请求。
*/
私有postDelete(请求选项:请求选项){
返回此.http[requestOptions.method](requestOptions.url,requestOptions.data);
}
/**
*
*@param{RequestOptions}RequestOptions
*@returns{Observable}
*/
私有get(requestOptions:requestOptions){
返回this.http.get(requestOptions.url);
}
/**
*
*@param{RequestOptions}RequestOptions标识请求的不同属性。
*/
httpRequest(请求选项:请求选项){
//发送http请求并使用method属性
//如果存在与请求一起发送的可观测数据
让observable=requestOptions.observable;
如果(可观察==未定义){
//如果没有可观察的,创建一个
observable=this.createObservable(请求选项);
}
可观察的(
(答复:任何)=>{
//调用响应处理程序
this.responseHandler(响应,请求选项);
},(错误)=>{
//调用错误处理程序
this.errorHandler(错误,请求选项);
}, () => {
//调用完整的处理程序
this.completeHandler(requestOptions);
}
);
}
私有responseHandler(响应、请求选项:请求选项){
//如果响应成功,则执行成功回调
if(response.issucess){
requestOptions.successCallBack(response.result);
//检查是否有无限滚动条且响应为空,然后禁用无限滚动条
if(requestOptions.infiniteScroller&&response.result.length==0){
requestOptions.infiniteScroller.enable(false);
}
}否则{
//如果响应不成功,请检查是否定义了notSuccessCallBack,
//如果定义了notSuccessCallBack,则执行它,否则执行默认的notSuccess callBacl
if(requestOptions.notSuccessCallBack){
//执行提供的not success回调
requestOptions.notSuccessCallBack(响应);
}else if(requestOptions.useDefaultNotSuccessCallBack){
//执行默认的not success回调
此.defaultNotSuccessResponse(响应);
}
}
}
私有errorHandler(错误,requestOptions:requestOptions | ForkOptions){
//检查提供的错误回调。
if(requestOptions.errorCallBack){
//执行提供的回调
requestOptions.errorCallBack(错误);
}else if(requestOptions.useDefaultErrorCallBack){
//如果您可以使用默认的错误处理程序
this.defaultErrorHandler(错误,请求选项);
}
}
/**
*
*@param{RequestOptions
public errors = new ReplaySubject<any>(1);
public void doRequest(): Observable<any> {
    this._http.get('').catch((err, source) => {
        this.errors.next(err);
        return source;
    });
}
public ngOnInit() {
    this._httpService.errors.subscribe(error => {
        this.scrollerEnabled = false;
    })
}