[英]Property 'json' does not exist on type 'Object'
我正在尝试使用 angular 2 HttpClient 通过 REST 获取数据。 我正在关注这里的 angular 教程https://angular.io/tutorial/toh-pt6 ,在Heroes 和 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”。
您可能会注意到,我有json().results
,而不是json().data
。 那是因为根据教程,服务器使用具有data
字段的对象进行响应,但我自己的服务器使用具有results
字段的对象进行响应。 如果您稍微向下滚动教程,您会看到这一点。
请注意服务器返回的数据的形状。 这个特定的内存 Web API 示例返回一个具有数据属性的对象。 您的 API 可能会返回其他内容。 调整代码以匹配您的 Web API。
为了解决这个问题,我尝试了这样的事情
(response: Response) => response.json().results as Order[]
当我这样做时, .json() 方法已解决,但出现了另一个错误
类型 Promise 上不存在属性结果
我尝试通过定义一个接口来解决这个问题
interface OrderResponse {
orders: Order[];
}
并将 get 调用修改为
.get<OrderResponse>(url)...
但这也不起作用。 另一个错误弹出
“OrderResponse”类型不能分配给“Response”类型。
需要注意的一件事是,在教程中他们使用了 Angular HttpModule,但在我的应用程序中,我使用的是新的 Angular HttpClientModule,所以也许这就是错误所在。
我是 Angular 2 的新手,这是我用它构建的第一个应用程序。 如果上面的代码对于新的 HttpClientModule 不再有效,我很感激有关如何使用新的 HttpClientModule 实现相同目标的任何帮助。
我发现了类似的问题Property 'json' does not exist on type '{}' and Property does not exist on type '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;
});
我完全理解,但我的问题是,该代码不在组件中,而是在服务中,因此调用 subscribe 并将结果分配给实例字段没有多大意义。
我需要我的服务返回包装在 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);
}
对于未来的访问者:在新的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,
...
],
...
更新:对于 rxjs > v5.5
正如一些评论和其他答案中提到的,默认情况下HttpClient将响应的内容反序列化为一个对象。 它的一些方法允许传递泛型类型参数以便对结果进行类型化。 这就是为什么不再有json()
方法的原因。
import {throwError} from 'rxjs';
import {catchError, map} from 'rxjs/operators';
export interface Order {
// Properties
}
interface ResponseOrders {
results: Order[];
}
@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<ResponseOrders >(this.baseUrl,{
params
}).pipe(
map(res => res.results || []),
catchError(error => _throwError(error.message || error))
);
}
请注意,您可以通过简单地调用toPromise()
轻松地将返回的Observable
转换为Promise
。
原始答案:
在你的情况下,你可以
假设您的后端返回如下内容:
{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[]
@Voicu提供正确的解决方案,谢谢您的提示。
对于未来的访问者:在新的HttpClient(Angular 4.3及更高版本)中,响应对象默认为JSON,因此您无需再执行response.json()。data。 只需直接使用响应即可。
解决它的另一种方法是使用以下代码片段:
JSON.parse(JSON.stringify(response)).data
这感觉很不对,但它有效
在 dotnet API angular MVC 应用程序上为我修复
检查您的 api url,当我更新 url 时,尾随/api/
已被删除。 没有它,根 url 将返回 html,即<
如果您来自 API 的响应是包含数据为 { status: 200, data: [{},{},...{}], message: 'Data fetched successfully'} 的对象,您可以执行以下操作。
首先将响应转换为字符串,然后解析响应并获取分配给变量的数据,该变量是对象数组。
this._employeeService.getEmployees()
.pipe(map(response => JSON.stringify(response)))
.subscribe(result => {
this.employeeList = JSON.parse(result).data;
// console.log(this.employeeList);
},(error)=>{
console.log(error);
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.