使用this.http实现针对角度服务的mixin

时间:2019-04-17 15:28:09

标签: angular typescript

这是与Angular 5和打字稿2.9.2一起使用的

我有一个类,该类既可以实现api,又可以充当应用程序中用户故事的状态。一开始看起来像这样:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/observable';
import { catchError, map, tap } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { AuthenticationService } from '../../core/services/authentication.service';
import { HttpErrorService } from '../../core/services/http-error.service';

import { manufacturersUrl } from '../constants';
import { Manufacturers } from '../interfaces/manufacturers.interface';
import { Device } from '../interfaces/device.interface';

@Injectable()
export class LocalService {
 public newDevice: Device;

  constructor (
    private http: HttpClient,
    private httpErrorService: HttpErrorService,
    private authenticationService: AuthenticationService) { 
      super();
      this.newDevice = {MAC : ''};
  }

  /**
   * getManufacturers api call for first page
   * @returns Observable
   */
  getManufacturers (): Observable<Manufacturers> {
    const requestBody = { 'num': 12 };

    return this.http.post<Manufacturers>(manufacturersUrl, requestBody).pipe(
      catchError(this.httpErrorService.handleError<Manufacturers>(`getManufacturers`))
    );
  }
}

如果我的交易代码没有在此服务中使视图更整洁,我会更高兴。因此,我想将getManufacturers移到 ./ extensionApi这样的文件中。 js 并导入以供使用,例如:

import { getManufacturers } from './extensionApi.ts';
//...
  private getManufacturers: Function;

  constructor (
    private http: HttpClient,
    private httpErrorService: HttpErrorService,
    private authenticationService: AuthenticationService) { 
      this.newDevice = {MAC : ''};

    this.getManufacturers = getManufacturers.bind(this);
  }

这种方法可以奏效,但不适用于这里。我收到一个编译错误:Untyped function calls may not accept type arguments与该函数的this.http部分有关。

我如何保持设计的模块化,却解决了编译问题?

附录

这三行完成了下面的答案

  constructor(http:HttpClient, httpErrorService: HttpErrorService,
    private authenticationService: AuthenticationService) { 
      super(http, httpErrorService);

实现

本地服务
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { AuthenticationService } from '@core/services/authentication.service';
import { HttpErrorService } from '@core/services/http-error.service';
import { Device } from '@usage/interfaces/device.interface';

import ApiClient from './extension-api';

@Injectable()
export class LocalService extends ApiClient {
 public newDevice: Device;

  constructor(http: HttpClient, httpErrorService: HttpErrorService,
    private authenticationService: AuthenticationService) { 
      super(http, httpErrorService);

      this.newDevice = {MAC : ''};
  }
}

extension-api

import { Observable } from 'rxjs/observable';
import { catchError, map, tap } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { HttpErrorService } from '@core/services/http-error.service';
import { manufacturersUrl } from '@usage/constants';
import { Manufacturers } from '@usage/interfaces/manufacturers.interface';

/**
* getManufacturers api call for first page
* @returns Observable
*/
export default class ApiService {
  constructor (private http: HttpClient,
    private httpErrorService: HttpErrorService){}

  getManufacturers(): Observable<Manufacturers> {
    const requestBody = { 'num': 12 };

    return this.http.post<Manufacturers>(manufacturersUrl, requestBody).pipe(
      catchError(this.httpErrorService.handleError<Manufacturers>(`getManufacturers`))
    );
   }
}

1 个答案:

答案 0 :(得分:1)

如果要在HttpClient中注入LocalService,那么HTTP调用实际上应该在该类中进行。使用导入的函数很好,但是在这种情况下,它确实混合了范式,因为您还在功能中绑定了this上下文-就像class compositionfunctional programmingOOD this上下文的用法

更标准的OOD方法将是扩展具有getManufacturers函数的基类。基类将注入HttpClient,并进行post调用。如果您不打算重用基类,则可能不值得

您的服务的第一个版本看起来绝对是标准的,所以我本人不会更改

export class BaseService {
  constructor(/*inject same classes as LocalService*/) {
  }
  public getManufacturers (): Observable<Manufacturers> {
     .....
  }
}

export class LocalService extends BaseService {

 constructor(/*inject the dependencies*/) {
      super(/* pass the dependencies to the BaseService*/)
  }
}