通过 http get in Angular 6 处理复杂对象

Processing a complex object by http get in Angular 6

我不明白如何处理我订阅的对象。对象结构如下:

{
  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"
                 }
              ]
       }
}

我通过服务申诉:

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`);
    }
}

有接口模型:

export class VideoListModel {
    constructor(
        public created_at: string,
        public description: string,
        public id: number,
        public items: any[],
        public name: string
    ) {}
}

然后我在组件中进行处理:

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();
    }

}

任务是按类型从对象中进行选择:"video"。通过 AJAX + jQuery 没有问题,并且在 Angular 中我相对较新。昨天刷了一堆视频课,找不到过滤这么复杂对象的例子

施工:

this._subscription2 = this.videoService.getVideoTape()
          .pipe(filter((data: VideoListModel[]) => data.items.type === 'video'))
          .subscribe((data: any) => {
              this.videoTape = data.data;
              console.log(this.videoTape);
          });

不起作用。结果是一个错误 "Property 'items' does not exist on type 'VideoListModel []'"。直觉上,我知道问题很可能在界面中,但我不明白如何修改界面以使过滤正常工作。如果有人遇到过滤复杂的对象,请告诉我如何解决这个问题。

您的 json 数据无效。

应该是

{
"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"
               }
            ]
     }
}

然后去http://json2ts.com/

您的模型将是

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;
}

您没有 VideoModels 数组,而是对象中的 items 数组。将整个内容通过管道传输到过滤器可以让您从数组中过滤出项目,但您有一个对象。您可以尝试以下解决方法:

创建这样的界面

interface Item {
  date: Date;
  text: string;
  images: string[];
  name: string;
  type: string;
}

export interface VideoModel {
  data: {
    date: Date;
    text: string;
    id: number;
    items: Item[];
  }
}

然后你就可以在你的Service中使用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))
  );
}

注意您的图片数组,因为它无效 json,字符串 []?过滤服务器端的类型以减少流量不是更好吗?

你说data是一个VideoListModel类型的array,因为数组没有属性items。你所做的就像 Array.items.type 这样没有意义。可能有更多奇特的解决方案,但请尝试将您的结果数组映射到一个可观察的对象,您可以在其中使用您的过滤器。

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();

使用 angular 版本 4+

时,另外像这样映射您的数据
getVideoTape() {
    return this.http.get<VideoListModel[]>(`http://ip_adress/api/v1/mixed_galleries/1`);
}

包括@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`);
    }
}