Угловое приведение ответа HttpClient - класс или интерфейс - PullRequest
0 голосов
/ 05 июня 2018

Я видел два метода для преобразования ответа в нашу пользовательскую модель данных.

Интерфейс

export interface User {
  id: number;
  name: string;
  more_complex_object: // so I am not sure how do this in right way. pass here another interface 
  //or just a object like {id: '', name: ''}. I show how to do this in class way...
}

И в обслуживании:

return this.http.get<User>...

И это прекрасно, нет необходимости делать что-то большее.

Класс

export interface Deserializable {
  deserialize(input: any): this;
}

export class ComplexModel implements Deserializable {
  field1: string;
  field2: number;
  field3: number;

  deserialize(input: any): this {
    Object.assign(this, input);
    return this;
  }
}

export class User implements Deserializable {
 id: number;
 name: string;
 complex: ComplexModel;

 deserialize(input: any): this {
   Object.assign(this, input);
   this.complex = new ComplexModel().deserialize(input.complex));
   return this;
 }
}

И в обслуживании

return this.http.get('/users/id/').pipe(
  map(user => new User().deserialize(user))
);

Как мы можемсм. в методе класса мы должны вручную создать объект.Это хорошо с объектом, как указано выше, но когда у нас есть более сложный объект или массив объектов, мы должны сделать что-то вроде этого:

return this.http.get('/users').pipe(
  map(users => {
    if (users instanceof Array) { // <- to avoid 'object has no method map' error
      return users.map(user => {
        return new User().deserialize(user);
      });
    }
  })
);

Классическим способом мы имеем гораздо более сложный код.И, наконец, вопросы:

Есть идеи, как сделать это как можно лучше?Какие методы лучше для вас и почему?

Интерфейс выглядит более красиво, но у нас нет «реального объекта», поэтому мы не можем использовать методы класса и т. Д., Верно?

В классе мы получаем реальный объект, но так ли он нужен?

Ответы [ 4 ]

0 голосов
/ 26 мая 2019

Объяснение этому есть в книге: "Угол вверх и бег" Шьяма Сешадри.Я цитирую прямо из книги Ch9 «Выполнение HTTP-вызовов на Angular», стр. 178:

". Важно отметить, что HttpClient может обеспечить гарантию типа в вашем коде. Мы используем эту функциюв методах getStocks () и toggleFavor ite (). Одним из результатов этого является то, что нам нужно изменить наш stock.ts с класса TypeScript на интерфейс TypeScript. Почему это так? Хотя нам это не нужно, Angular делаетпростое приведение типа тела ответа к определенному нами типу, но у TypeScript (и ECMAScript под ним) нет удобного и простого способа преобразования простого старого объекта JavaScript в прототипический объект класса JavaScript / TypeScript.наш ответ от StockService будет иметь все свойства класса Stock, он не будет иметь доступных функций (в частности, isPositiveChange ()). Мы могли бы написать конвертер, но он того стоит только в очень специфических случаях. Это прощепросто использовать TypeScript для безопасности типов и работыс другими способами инкапсуляции (либо на уровне компонентов, либо, возможно, в качестве службы Angular). "

Пожалуйста, обратитесь к книге для получения более подробных объяснений

0 голосов
/ 05 июня 2018
export interface UserModel {
  id: number;
  name: string;
  more_complex_object: MoreComplexObject; // your MoreComplexObject interface
  comments: Comment[]; // your Comment interface
}

Как вы видели выше, вы можете вкладывать интерфейсы вместе, чтобы создавать сложные типы данных в соответствии с вашими бизнес-потребностями.

Для вопроса о реальных объектах, почему бы вам не создать классчто берет вашу UserModel модель из конструктора?

class AppUser {
    constructor(private userModel: UserModel) {}

    someMethod() {
        // use this.userModel for logic
    }
}
0 голосов
/ 05 июня 2018

если вы используете httpClient, то вы можете просто сделать это

this.userService.getUsers().subscribe(data=> this.users= data);

означает, что нет необходимости в десериализации логики, так как она под капотом отображает ваш ответ на ваш тип объекта,

export interface user {
 id: number;
 name: string;
 complex: ComplexModel;
}

export interface ComplexModel {
 field1: string;
  field2: number;
  field3: number;
}

это работает для меня очень хорошо, если вы действительно используете интерфейс, то вы можете отдельно создавать классы обслуживания, которые могут работать на вашем объекте, например.

export class ComplexModleManager() {
  complexObj : ComplexModle;
  constructor(private obj: ComplexModle) {
    this.complexObj = obj;
  }

  method1(){
   Console.log(complexObj.prop1);
  }     
}

thisто, как вы отделяете свою боль и логику реализации, которые работают с этим объектом боли.

0 голосов
/ 05 июня 2018

Я использую интерфейсы.Еще не использовали классы в Angular.Есть хорошая статья по этому вопросу: Классы против интерфейсов в TypeScript Возможно, чтение этого поможет вам решить, какой из них использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...