Как запросить REST API с использованием строгой типизации - PullRequest
1 голос
/ 07 июня 2019

Я не могу разобрать выходные данные из API (массив проектов находится внутри атрибута results), поскольку TS говорит, что results не является атрибутом класса Project.

Класс проекта:

export class Project {
  project_id: string;
  project_name: string;
  project_code: string;
  project_lead: string;
  project_cost_center: number;
  project_number: string;
  budget: number;
  team: string;
  provision: boolean;
  project_groups: any;
  project_networks: any;
  applications: any;
  project_environments: any;
  subscription: string;
  created_at: string;
}

Пример ответа API:

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "http://localhost:8000/api/v1/projects/COA/",
            "project_id": 57,
            "project_name": "Compliance Application",
            "project_code": "COA",
            "project_lead": "John Doe",
            "project_cost_center": "9005",
            "project_number": "900512I320",
            "budget": 600.0,
            "team": "http://localhost:8000/api/v1/teams/TTA/",
            "provision": true,
            "project_groups": [],
            "project_networks": [
                "http://localhost:8000/api/v1/ip-network/23/"
            ],
            "applications": [
                "http://localhost:8000/api/v1/applications/COA/"
            ],
            "project_environments": [
                "http://localhost:8000/api/v1/environments/8/",
                "http://localhost:8000/api/v1/environments/7/"
            ],
            "subscription": "http://localhost:8000/api/v1/subscriptions/128a4bb5-604d-11e9-86ee-88e9fe8080e6/",
            "created_at": "2019-04-16T13:37:05.293000Z"
        }
    ]
}

Это то, что я использую:

Angular CLI: 8.0.1
Node: 12.4.0
OS: darwin x64
Angular: 8.0.0
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.800.1
@angular-devkit/build-angular     0.800.1
@angular-devkit/build-optimizer   0.800.1
@angular-devkit/build-webpack     0.800.1
@angular-devkit/core              8.0.1
@angular-devkit/schematics        8.0.1
@angular/cli                      8.0.1
@ngtools/webpack                  8.0.1
@schematics/angular               8.0.1
@schematics/update                0.800.1
rxjs                              6.4.0
typescript                        3.4.5
webpack                           4.30.0

Мой начальныйфункция выглядела так:

// HttpClient API get() method => Fetch project list
  getProjects(): Observable<Project[]> {
    return this.http.get<Project[]>(this.apiURL + '/projects')
      .pipe(
        retry(1),
        catchError(this.handleError)
      )
  }

Конечно, я должен использовать RxJS map с данными из операции GET для итерации, затем по results и получения массива объектов.

Если я сделаю

// HttpClient API get() method => Fetch project list
  getProjects(): Observable<Project[]> {
    return this.http.get<Project[]>(this.apiURL + '/projects')
      .pipe(
        map(data => data.json().results),
        retry(1),
        catchError(this.handleError)
      )
  }

Затем я получу сообщение о том, что класс Project не имеет атрибута json().Это потому, что я привел .get() метод к Project[]?Если да, то как мне это настроить?

Я ожидаю, что это будет правильно, но я довольно плохо знаком с Angular, и документация не помогает.

Ответы [ 3 ]

1 голос
/ 07 июня 2019

API не возвращает массив Project, у вас есть 2 решения для решения вашей проблемы:

Первое решение, не используйте типизированный ответ:

getProjects(): Observable<Project[]> {
  return this.http.get(this.apiURL + '/projects')
    .pipe(
      map(data => data.results),
      retry(1),
      catchError(this.handleError)
    );
}

Второе решение с использованием типизированного ответа :

Теперь HttpClient.get () возвращает Observable типизированного HttpResponse, а не только данные JSON.

export interface ApiProjectResponse {   
  count: number;
  next: any;
  previous: any;
  results: Project[];
}

getProjects(): Observable<Project[]> {
  // HTTP GET /projects returns an ApiProjectResponse
  return this.http.get<ApiProjectResponse>(this.apiURL + '/projects')
    .pipe(
      map(data => data.results),
      retry(1),
      catchError(this.handleError)
    );
}
0 голосов
/ 07 июня 2019

Если в результате вы ожидаете список Projects, он уже есть в ваших данных, потому что вы typed равны Project[], что приводит к array of Project.

с вашимС данными вы можете делать такие вещи, как data.length, чтобы увидеть, сколько у вас записей Project.Это основные манипуляции с массивами.

На Array нет .results.Вы можете просто console.log(data) увидеть весь Array и работать с этим.data.forEach() проходит через каждый Project внутри вашего массива и так далее.Вы можете передать его на *ngFor="let project of projects", и он пройдет для вас Array.

0 голосов
/ 07 июня 2019

Возможно, проблема в том, что ваш API не возвращает массив проектов.Его структура может быть другой (что-то вроде APIResponse).Но в вашем методе вы хотите вернуть массив проектов.

Если проблема заключается в этом, то вы должны написать что-то вроде этого.

// HttpClient API get() method => Fetch project list
  getProjects(): Observable<Project[]> {
    return this.http.get<APIResponse>(this.apiURL + '/projects')
      .pipe(
        map(data => data.results),
        retry(1),
        catchError(this.handleError)
      )
  }

И ваш класс APIResponse должен быть таким:

export class APIResponse {   
  count: number;
  next: any;
  previous: any;  
  results: Project[];
}
...