首页 > 解决方案 > 使用 this.http 为 Angular 服务实现 mixin

问题描述

这是 Angular 5 和 typescript 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 argumentsthis.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 : ''};
  }
}

扩展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`))
    );
   }
}

标签: angulartypescript

解决方案


如果您正在注入HttpClientLocalService那么 HTTP 调用确实应该在该类中进行。使用导入的函数很好,但在这种情况下,它真的混淆了范式,因为你也在函数中绑定了上下文——this就像使用上下文一样class compositionfunctional programmingOODthis

更标准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*/)
  }
}


推荐阅读