【问题标题】:ionic/angular- How to use interfaces correctly?ionic/angular-如何正确使用接口?
【发布时间】:2018-08-01 20:59:58
【问题描述】:

我对 angular/ionic 应用程序开发很陌生。我在某处读到以下内容

接口仅在编译时。这仅允许您检查接收到的预期数据是否遵循特定结构。

我正在制作一个离子应用程序,API 服务将一些数据返回给用户。假设它是一个登录函数,API 服务为此返回数据。

我在 Ionic 中创建了一个提供程序,从中使用 HTTPClient 对 API 进行 HTTP 调用。

//Provider

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

interface LoginResponse {
  success: boolean;
  message: string;
  token: string;
  userId: number;
}
@Injectable()
export class LoginServicesProvider {
  constructor(public http: HttpClient) {
  }

  login(reqData): Observable<LoginResponse[]> {
    return this.http.post<LoginResponse[]>('localhost:3000/api/login', reqData);
  }
}

如你所见,我创建了一个名为 LoginResponse 的接口

而登录组件的代码如下:

//Component

import { LoginServicesProvider } from './../../providers/login-services/login-services';
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'page-login-page',
  templateUrl: 'login-page.html',
})
export class LoginPage {
  constructor(private loginService: LoginServicesProvider) {
  }

  onSubmit() {
    let reqParams = {
    email: 'afakeemail@id.com',
    password: 'password',
    };

    this.loginService.login(reqParams).subscribe(res => {
        console.log('success');
    });
  }
}

对于这个例子,我只是向控制台打印一条消息。

现在是我的问题

1) 如前所述,我的 LoginResponse 接口是否检查接收到的数据?如果没有,我应该如何/在哪里实现该签入提供程序或组件?

2) 如果我在单个提供程序中有多个接口,比如说,一个用于登录数据,另一个用于用户配置文件数据或其他什么,我应该把它放在哪里?我可以将其保存在单独的文件中并导出吗?我没有看到任何用于创建接口的离子命令

谢谢!我不想从错误开始我的职业生涯。这就是为什么我想发布这个。

【问题讨论】:

  • 接口可以像任何其他结构一样导出。不要过度依赖脚手架工具来为您编写代码,因为您必须自己维护它(即没有离子命令 -> 谁在乎?)。使用接口 描述 HTTP 响应类型的正确方法,但与所有类型一样,它们只是编译时的,不添加任何行为。如果您不知道服务器生成的响应对象的形状,则必须手动检查。
  • 我知道服务器产生的响应对象的形状。我根据那个创建了那个接口,但是如果服务器返回的响应有点大怎么办。我应该单独检查每个对象的正确数据类型吗? @AluanHaddad
  • 这是一个信任问题,如果你知道服务器响应匹配,我不会担心。但也不要根据性能来选择。你也可以find this interesting

标签: angular typescript ionic-framework ionic2


【解决方案1】:

Typescript 中的接口仅提供对象形状的描述。如果在 TypeScript 中创建了一个对象,编译器可以推断该对象是否与接口兼容。在运行时接口被擦除,因此不会检查对象是否与接口兼容。当您使用post&lt;T&gt; 发出请求时,您基本上是在告诉编译器您期望的对象形状作为T 的响应,但不会执行任何检查来确保这一点。

您可以在一个文件中拥有任意数量的接口,您可以将它们从该文件中导出,然后将它们导入另一个文件中,就像您使用类或函数一样。如何组织代码取决于您。

如果您想确保对象在运行时正确实现,请参阅here

【讨论】:

  • 我还要补充一点,这也是与其他开发人员就你的项目(甚至是 10 个月后的你自己)交流对象形状的好方法
【解决方案2】:

正如您提到的打字稿中的接口仅用于定义合同。因此,在您的示例中,您只是期望来自服务器的日志响应,其中包含您在界面中提到的属性。没有像接口那样的约束,我们应该提到 JSON 响应中返回的所有属性。如果您需要 JSON 响应中不存在的属性,您甚至可以在界面中添加更多属性。 因此,在您的具体示例中,通过使用接口,您可以在将来检查代码时了解 API 的规范。所以下面将是我的实现

我将创建一个名为 ILoginRequest.ts 的新文件并声明名为 ILoginRequest 的接口

export interface ILoginRequest {
 email:string;
 password:string;
}

并使用该接口作为提供者类中 requestData 输入参数的类型

login(reqData:ILoginRequest ): Observable<LoginResponse[]> {
return this.http.post<LoginResponse[]>('localhost:3000/api/login', reqData);

}

因此,如果我们在项目中的其他任何地方使用提供程序类中的登录函数,我们就知道应该为登录方法提供什么输入,以及该函数的预期结果是什么。

并且在调用页面中,会将来自 api 的输出分配到 loginResponse 变量中,该变量是接口 LoginResponse 类型。因此,无论何时我们在类中使用此变量,我们都知道我们可以使用哪些属性,并且我们在 IDE 中获得了智能感知支持

export class LoginPage {
 private loginResponse : LoginResponse;
 constructor(private loginService: LoginServicesProvider) {
 }

onSubmit() {
let reqParams = {
email: 'afakeemail@id.com',
password: 'password',
};

this.loginService.login(reqParams).subscribe((res:LoginResponse) => {
    console.log('success');
    this.loginResponse = res;
});

} }

有关 typescript 中接口使用的更多详细信息,您可以查看此link

关于将接口保存在哪里,据我所知,这只是开发人员的偏好,您可以在“app”目录中创建名为接口的单独文件夹,并为每个接口创建新文件。

【讨论】:

    猜你喜欢
    • 2020-05-06
    • 2018-01-02
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    相关资源
    最近更新 更多