typescript 在 Angular 6 中通过 http get 处理复杂对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50524711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Processing a complex object by http get in Angular 6
提问by Artemy Khodorev
I do not understand how to handle the object I subscribe to. The object is the following structure:
我不明白如何处理我订阅的对象。对象是以下结构:
{
data:{
date: "2018-02-20 13:10:23",
text: "Описание",
id: 1,
items: [
0: {
date: "2018-02-20 13:10:23",
text: "Описание",
images: [
0: "image1.jpg",
1: "image2.jpg"
],
name: "Изображения",
type: "images"
},
1: {
date: "2018-02-20 13:10:23",
text: "Описание",
image: null,
type: "video",
url: "https://www.youtube.com/embed/v64KOxKVLVg"
}
]
}
}
I make an appeal through the service:
我通过服务提出上诉:
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
@Injectable()
export class VideoService {
constructor(private http: HttpClient) {}
getVideoTape() {
return this.http.get(`http://ip_adress/api/v1/mixed_galleries/1`);
}
}
There is an interface model:
有一个接口模型:
export class VideoListModel {
constructor(
public created_at: string,
public description: string,
public id: number,
public items: any[],
public name: string
) {}
}
And I do the processing in the component:
我在组件中进行处理:
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Observable, Subscription} from 'rxjs';
import {filter} from 'rxjs/operators';
import {VideoService} from '../shared/services/video.service';
import {VideoListModel} from '../../shared/models/video-list.model';
@Component({
selector: 'app-video-index',
templateUrl: './video-index.component.html',
styleUrls: ['./video-index.component.scss']
})
export class VideoIndexComponent implements OnInit, OnDestroy {
private videoTape = [];
private _subscription2: Subscription;
constructor( private videoService: VideoService ) { }
ngOnInit() {
this._subscription2 = this.videoService.getVideoTape()
.subscribe((data: VideoListModel[]) => {
this.videoTape = data;
console.log(this.videoTape);
});
}
ngOnDestroy() {
this._subscription2.unsubscribe();
}
}
The task is to make a selection from objects by type: "video". Through AJAX + jQuery did it without problems, and in Angular I'm relatively new. Shoveled a bunch of video lessons yesterday, but nowhere are examples of filtering such complex objects.
任务是按类型从对象中进行选择:“视频”。通过 AJAX + jQuery 没有问题,而且在 Angular 中我相对较新。昨天铲了一堆视频课程,但没有过滤这种复杂对象的例子。
Construction:
建造:
this._subscription2 = this.videoService.getVideoTape()
.pipe(filter((data: VideoListModel[]) => data.items.type === 'video'))
.subscribe((data: any) => {
this.videoTape = data.data;
console.log(this.videoTape);
});
does not work. The result is an error saying "Property 'items' does not exist on type 'VideoListModel []'". Intuitively, I understand that the matter is most likely in the interface, but I can not understand how to modify the interface so that the filtering works correctly. If someone encountered filtering complex objects, tell me please how to solve this problem.
不起作用。结果是一个错误,提示“属性 'items' 在类型 'VideoListModel []' 上不存在”。直觉上,我明白这个问题最有可能出在界面上,但我无法理解如何修改界面以使过滤正常工作。如果有人遇到过滤复杂对象,请告诉我如何解决这个问题。
采纳答案by Felix Lemke
You don't have an array of VideoModels but an array of items
in an object. Piping the whole content to a filter lets you filter items out of arrays, but you have an object. You could try the following workaround:
您没有一个 VideoModel 数组,而是items
一个对象中的数组。将整个内容传送到过滤器可以让您从数组中过滤项目,但您有一个对象。您可以尝试以下解决方法:
Create an interface like this
创建一个这样的界面
interface Item {
date: Date;
text: string;
images: string[];
name: string;
type: string;
}
export interface VideoModel {
data: {
date: Date;
text: string;
id: number;
items: Item[];
}
}
Then you can use HttpClient in your Service as follows
然后你可以在你的服务中使用 HttpClient 如下
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
[...]
getVideoTape(): Observable<VideoModel> {
return this.http.get<VideoModel>(url).pipe(
map(model => {
const items = model.data.items.filter(item => item.type === 'video');
model.data.items = items;
return model;
}),
catchError(error => console.error(error))
);
}
Pay attention to your images array, as it isn't valid json, string[]? Wouldn't it be better to filter the types serverside in order to reduce traffic?
注意你的图像数组,因为它不是有效的 json, string[]? 过滤服务器端的类型以减少流量不是更好吗?
回答by Fussel
You say that data
is an array
of type VideoListModel
, the array of cause has no property items
. What you did is like Array.items.type
which does not make sense. There are probably more fancy solutions but try mapping your result array to an observable where you can use your filters on.
你说的data
是一个array
类型VideoListModel
,原因的数组没有属性items
。你所做的就像Array.items.type
是没有意义的。可能有更多奇特的解决方案,但请尝试将结果数组映射到可在其中使用过滤器的 observable。
this._subscription2 = this.videoService.getVideoTape()
.pipe(
map(data => from(data).pipe(filter((d: VideoListModel) => d.items.type === 'video')))
tap(data => data.subscribe(d => {
this.videoTape.push(d);
}))
).subscribe();
Additionally map your data like this when using angular version 4+
另外在使用 angular 版本 4+ 时像这样映射您的数据
getVideoTape() {
return this.http.get<VideoListModel[]>(`http://ip_adress/api/v1/mixed_galleries/1`);
}
回答by Piero
your json data is not valid.
您的 json 数据无效。
it should be
它应该是
{
"data":{
"date": "2018-02-20 13:10:23",
"text": "tt",
"id": 1,
"items": [
{
"date": "2018-02-20 13:10:23",
"text": "Описание",
"images": [
"image1.jpg",
"image2.jpg"
],
"name": "Изображения",
"type": "images"
},
{
"date": "2018-02-20 13:10:23",
"text": "Описание",
"image": null,
"type": "video",
"url": "https://www.youtube.com/embed/v64KOxKVLVg"
}
]
}
}
then going to http://json2ts.com/
your model would be
你的模型是
export interface Item {
date: string;
text: string;
images: string[];
name: string;
type: string;
image?: any;
url: string;
}
export interface Data {
date: string;
text: string;
id: number;
items: Item[];
}
export interface VideotapeAnswer {
data: Data;
}
回答by Prabhat Maurya
Include the changes suggested by @Piero and your service is not returning any observable.
包括@Piero 建议的更改,您的服务不会返回任何可观察的。
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
@Injectable()
export class VideoService {
constructor(private http: HttpClient) {}
getVideoTape():Observable<any> {
return this.http.get(`http://ip_adress/api/v1/mixed_galleries/1`);
}
}