我有一个服务和一个组件。
一些.service.ts
import { Injectable } from '@angular/core';
import { HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { SomeClass } from '../model/some.class';
@Injectable()
export class SomeService {
constructor(private http: HttpClient) {}
getData(): Observable<SomeClass[]> {
let url = 'someUrlEndpoint';
let results = this.http.get<SomeClass[]>(url);
return results;
}
}
some.component.ts
import { SomeService } from './service/some.service';
import { SomeClass } from './model/some.class';
export class SomeComponent {
someClass: SomeClass[];
constructor(private someService: SomeService)
ngOnInit() {
this.getData()
}
getData() {
this.someService.getData()
.subscribe(res => this.someClass = res);
}
}
一些.class.ts
export class SomeClass {
title: string;
status: string;
numberOfPersons: number;
persons: string;
...
constructor(json: any = "") {
this.title = json.title;
this.status = getStatus(json.status);
this.numberOfPersons = getNumberOfPersons(json.persons);
this.persons = json.persons;
...
}
getStatus(value: number) {
let status = StatusCase.ongoing;
if(value == 1) {status = StatusCase.done}
if(value == 2) {status = StatusCase.completeWithDeviations}
if(value == 3) {status = StatusCase.aborted}
return status;
}
getPersons(value: string) {
let persons = 0;
get persons splitted by comma, count it up and return
return persons;
}
}
export enum StatusCase {
ongoing = "Ongoing";
aborted = "Aborted";
completeWithDeviations = "Complete with deviations";
done = "Done";
}
我能够获取数据,但不是以我想要的方式。
现在,由于 httpClient 不返回 SomeClass 的实例,因此它不会通过构造函数,并且应用程序将无法获得所需的正确数据。 那么"新的SomeClass(data("在哪里适合呢?是否可以以构建httpClient的方式进行操作?或者我必须获取非类型化数据 (json( 并执行 for 循环以传统方式填充 someClass:SomeClass[]?
或者是否有另一种更智能的方法来填充计算属性? 使用拦截器操作响应中的数据?似乎响应上的拦截器仅用于错误。
.get<SomeClass[]>
不执行任何操作。它仅在开发过程中有用。您可以运行映射运算符并返回类的实例。
您可以使用像class-transformer这样的库将HTTP响应纯JavaScript映射到类对象中:
// assuming that your json response from the http call is an array
const obs: Observable<SomeClass[]> = this.http.get(url).map(res =>
plainToClass(SomeClass, res));
short answer:
不是没有办法做到的。下面的解释,或者只是跳到这个问题的解决方案,尽管您在问题中概述了它。
长答案
当您在此处使用泛型时.get<SomeClass[]>()
您将向打字稿提供更多信息,以帮助在转译时(静态 + 强类型(实现代码正确性。请记住,Typescript 只是 JS 的一个超集,所以当运行时发生时,无法真正知道你有一个类。因为 JS 中的类本身只是原型模型的语法糖。
所以引擎盖下仍在发生的事情JSON.parse(jsonStr)
..由于鸭子类型,此对象(如果您的类正确匹配传入的 JSON(将能够按原样满足要求。如果你想实例化一个类,你必须自己做。
Solution
我们可以将密钥分散到实例的简单方法
this.http.get<SomeClass[]>(url)
.pipe(
map( someClasses =>
someClasses.map( someClass => Object.assign(new SomeClass(), { ...someClass } )
)
)
.subscribe( someClasses => results = someClasses);
or constructor route..附言 你不需要在你的构造函数中使用any
。
export class SomeClass {
constructor(someClass: SomeClass) {
this.title = someClass.title;
this.status = this.getStatus(someClass.status);
//...
}
getStatus(value: number) {
//...
}
}
<小时 />this.http.get<SomeClass[]>(url)
.pipe(
map( someClasses =>
someClasses.map( someClass => new SomeClass(someClass) )
)
)
.subscribe( someClasses => results = someClasses);