Подтвердить что ты не робот

Свойство 'json' не существует в типе 'Object'

Я пытаюсь получить данные через REST с угловым 2 HttpClient. Я следую угловому учебнику здесь https://angular.io/tutorial/toh-pt6, а в разделе Герои и HTTP вы увидите этот фрагмент кода, используемый для извлечения данных героя через http.

getHeroes(): Promise<Hero[]> {
  return this.http.get(this.heroesUrl)
         .toPromise()
         .then(response => response.json().data as Hero[])
         .catch(this.handleError);
}

И ниже - аналогичная версия, которую я написал в своей заявке

fetch(startIndex: number, limit: number): Promise<Order[]> {
    let url = this.baseUrl + "&startIndex=" + startIndex + "&limit=" + limit;

    return this.http.get(url)
                .toPromise()
                .then(response => response.json().results as Order[])
                .catch(this.handleError);
}

Я использую InteliJ Idea, и есть красная строка в ответе response.json(), и даже когда я пытаюсь построить с помощью ng build, я получаю ошибку.

Свойство 'json' не существует в типе 'Object'.

Вы можете заметить, что вместо json().data меня есть результаты json().results. Это связано с тем, что в соответствии с учебным пособием сервер ответил объектом, у которого есть поле data но мой собственный сервер отвечает объектом, у которого есть поле results. Если вы немного прокрутите учебник, вы увидите этот момент.

Обратите внимание на форму данных, возвращаемых сервером. Этот конкретный пример веб-API в памяти возвращает объект с свойством data. Ваш API может вернуть что-то еще. Откорректируйте код в соответствии с вашим веб-интерфейсом.

В попытке исправить это, я попробовал что-то вроде этого

(response: Response) => response.json().results as Order[]

Когда я это сделал, метод.json() был разрешен, но появилась еще одна ошибка, которая

Имущественных результатов не существует по типу Promise

Я попытался исправить это, указав интерфейс

interface OrderResponse {
    orders: Order[];
}

И изменил запрос на вызов

 .get<OrderResponse>(url)...

Но это тоже не сработало. Появилась еще одна ошибка

Тип "OrderResponse" не присваивается типу "Ответ".

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

Я новичок в Angular 2, и это первое приложение, с которым я строю. Если вышеуказанный код больше недействителен с новым HttpClientModule, я был бы признателен за любую помощь в том, как добиться этого с новым HttpClientModule.

Я нашел похожие вопросы Свойство 'json' не существует в типе '{}', а свойство не существует в типе 'object', но ни один из ответов там не помог мне.

Обновить

Как и предполагалось, в новом HttpClientModule нет метода.json(). Я по-прежнему ценю помощь в том, как добиться такого же эффекта с новым модулем. Из руководства они сделали что-то вроде этого

http.get<ItemsResponse>('/api/items').subscribe(data => {
  // data is now an instance of type ItemsResponse, so you can do this:
  this.results = data.results;
});

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

Мне нужно мое обслуживание, чтобы вернуть массив Заказов, завернутых в Promise. Мои компоненты могут просто звонить

this.orderService.fetch(0, 10).then(orders => this.orders = orders)

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

.subscribe(data => {
    this.orders = data.results;
}
// and out of the get call I return my local variable orders like
return Promise.resolve(orders)

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

Обновить

В соответствии с запросом здесь приведен код для handleError

private handleError(error: any): Promise<any> {
    console.log('An error occured ', error);
    return Promise.reject(error.message || error);
}
4b9b3361

Ответ 1

Удовлетворение того, что ваш backend возвращает что-то вроде:

[{},{},{},...{}]

UPDATE: теперь, когда backend возвращает {results: [{},{}]}

в формате JSON, где каждый {} является сериализованным объектом, вам понадобится следующее:

// Somewhere in your src folder

export interface Order {
  // Properties
}

import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { Order } from 'somewhere_in_src';    

@Injectable()
export class FooService {
 ctor(private http: HttpClient){}

 fetch(startIndex: number, limit: number): Observable<Order[]> {
    let params = new HttpParams();
    params = params.set('startIndex',startIndex.toString()).set('limit',limit.toString());
    // base URL should not have ? in it at the en
    return this.http.get(this.baseUrl,{
       params
    })
    .map(res => res.results as Order[] || []); 
   // in case that the property results in the res POJO doesnt exist (res.results returns null) then return empty array ([])
  }
} 

Я удалил секцию catch, так как это могло быть архивировано через HTTP-перехватчик. Проверьте документы. В качестве примера:

https://gist.github.com/jotatoledo/765c7f6d8a755613cafca97e83313b90

И, чтобы потреблять, вам просто нужно называть его так:

// In some component for example
this.fooService.fetch(...).subscribe(data => ...); // data is Order[]

Ответ 2

Для будущих посетителей: в новом HttpClient (Angular 4. 3+) объект response по умолчанию JSON, поэтому вам больше не нужно делать response.json().data. Просто используйте response напрямую.

Пример (измененный из официальной документации):

import { HttpClient } from '@angular/common/http';

@Component(...)
export class YourComponent implements OnInit {

  // Inject HttpClient into your component or service.
  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.http.get('https://api.github.com/users')
        .subscribe(response => console.log(response));
  }
}

Не забудьте импортировать его и включить модуль под импортом в ваш проект app.module.ts:

...
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    BrowserModule,
    // Include it under 'imports' in your application module after BrowserModule.
    HttpClientModule,
    ...
  ],
  ...