Свойство '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);
}
Ответы
Ответ 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,
...
],
...