【问题标题】:Processing a complex object by http get in Angular 6在Angular 6中通过http get处理复杂对象
【发布时间】:2018-11-04 14:07:14
【问题描述】:

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

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

}

任务是按类型从对象中进行选择:“视频”。通过 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);
          });

不起作用。结果是一个错误,提示“类型'VideoListModel []'上不存在属性'项目'”。直觉上,我明白这件事很可能在界面中,但我无法理解如何修改界面以使过滤正常工作。如果有人遇到过滤复杂对象,请告诉我如何解决这个问题。

【问题讨论】:

    标签: angular typescript filter angular6 rxjs6


    【解决方案1】:

    您说dataarray 类型的VideoListModel,原因数组没有属性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`);
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 您的解决方案破坏了类型。查看我的答案以防止这种情况发生。
      • 是的,它没有根据我刚刚告诉添加此代码为他工作的服务类型返回。同样,如果他想重构,他可以做到。顺便感谢您的评论。@ngfelixl
      【解决方案3】:

      对象中没有 VideoModel 数组,而是 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[];
        }
      }
      

      然后你可以在你的服务中使用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,字符串 []?过滤服务器端的类型以减少流量不是更好吗?

      【讨论】:

      • 非常感谢您!是工作!正如我所怀疑的,问题出在界面上。回答您关于有效 json 的问题:数据库位于服务器端,我没有机会调整其架构。这意味着“按顺序过滤服务器端的类型”,我不知道)显然我还没有那么有经验)
      • 哦,我明白你在说什么。在我的主题中,它不是 json 文件。它只是控制台 Chrome 的副本,当我使用 console.log() 返回数据时:)
      • 不客气!如果您无权访问服务器,并且服务器不提供类型过滤器,您可能必须实现客户端过滤器。如果您有权访问服务器的接口,它可能会提供一些用于过滤的 url 参数。 Http get 请求做或应该始终将附加数据附加到 url,例如 http://yoururl.com/pathto/yourentity/?type=video
      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-27
        • 1970-01-01
        • 1970-01-01
        • 2019-12-31
        • 1970-01-01
        • 2012-12-19
        • 2014-08-22
        • 2018-11-30
        相关资源
        最近更新 更多