【问题标题】:Angular - HttpClient: Map Get method object result to array propertyAngular - HttpClient:将获取方法对象结果映射到数组属性
【发布时间】:2017-10-12 01:37:38
【问题描述】:

我正在调用一个返回 JSON 对象的 API。我只需要将数组的值映射到 Observable 。如果我调用只返回数组的 api,我的服务调用就可以了。

下面是我的示例代码..

// my service call ..
import { Injectable } from '@angular/core';
import {Observable} from 'rxjs/Observable';
import {Show} from '../models/show';
import {HttpClient} from '@angular/common/http';

@Injectable()
export class MyService {

  constructor(private http: HttpClient ) { }


  findAllShows(): Observable<Show[]> {
    return this.http
      .get<Show[]>(`${someURL}/shows`)
  }
}

如果返回的是 JSON 对象,如下所示,则失败..

// Service API that FAILS ...
{
  "shows": [
    {
      "id": "123f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-13 15:54:47",
      "name": "Main Show1"
    },
    {
      "id": "456f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-14 15:54:47",
      "name": "Main Show2"
    },
    {
      "id": "789f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-17 15:54:47",
      "name": "Main Show3"
    }
  ]
}

如果我只返回数组,这个就可以了

// Service API that Works ...
[
    {
      "id": "123f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-13 15:54:47",
      "name": "Main Show1"
    },
    {
      "id": "456f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-14 15:54:47",
      "name": "Main Show2"
    },
    {
     "id": "789f9165-80a2-41d8-997a-aecc0bfb2e22",
      "modified": "2017-08-17 15:54:47",
      "name": "Main Show3"
    }
  ]

如何将 JSON 对象 Observable 映射到 Array Observable 中???

【问题讨论】:

    标签: arrays json angular rxjs angular-httpclient


    【解决方案1】:

    您可以简单地 .map() 您的 http 调用,即 Observable,返回您想要的数据类型。

    findAllShows(): Observable<Show[]> {
        return this.http
            .get(`${someURL}/shows`)
            .map(result=>result.shows)
    }
    

    你的httpClient.get() 应该返回一个Observable,你已经明确表示它认为Observable&lt;Show[]&gt;。你.map() 是一个将 observable 转换为新的运算符。

    更多关于.map()操作员:http://reactivex.io/documentation/operators/map.html

    更新:

    对于 RXJS 版本 6 及更高版本,只需使用.pipe() 来管道.map() 运算符:

    findAllShows(): Observable<Show[]> {
        return this.http
            .get(`${someURL}/shows`)
            .pipe(map(result=>result.shows))
    }
    

    【讨论】:

    • 我尝试并得到了错误...属性 'shows' 在类型 'Response' 上不存在。
    • @Netwobble 不,不要将其强制转换为类型Response。查看我的编辑。
    • 'map' 功能对httpClient仍然不可用
    • @ArunRedhu httpClient.get() 应该返回一个Observable,我们通过Observable&lt;Show[]&gt; 明确说明了这一点。 .map() 是一个将可观察对象转换为新对象的运算符。
    • get('') 没有类型参数应该返回 Observable。尝试使用 .map(res => res['shows'])
    【解决方案2】:

    最新的HttpClient 应该用来代替http 没有map 方法。您应该先通过import { map } from 'rxjs/operators'; 导入它 那么你应该这样使用它:

    this.http.get(`${someURL}/shows`).pipe(
            map(res => res['shows'])
        )
    

    【讨论】:

    • 确保在您的 tsconfig.json 文件中有 "suppressImplicitAnyIndexErrors": true, 以抑制错误 TS7015。
    【解决方案3】:

    谢谢大家, 通过提供服务器发回的传输对象接口,我能够通过组合来自@Arun Redhu 的响应来找到解决方案。然后由@CozyAzure 提供的解决方案通过使用 .map() 将一个 Observable 转换为正确的 Observable Show[]。

    下面为感兴趣的人提供完整的解决方案。

    import {Observable} from 'rxjs/Observable';
    import {Contact} from '../models/show';
    import {environment} from '../../../environments/environment';
    // Use the new improved HttpClient over the Http
    // import {Http, Response} from '@angular/http'; 
    import {HttpClient} from '@angular/common/http';
    
    // Create a new transfer object to get data from server
    interface ServerData {
      shows: Show[];
    }
    
    @Injectable()
    export class ShowsService {
    
      constructor(private http: HttpClient ) { }
    
    // want Observable of Show[]
      findAllShows(): Observable<Show[]> {  
        // Request as transfer object <ServerData>
        return this.http
          .get<ServerData>(`${apiURL}/shows`)
         // Map to the proper Observable I need 
          .map(res => <Show[]>res.shows); 
    
      }
    }
    

    现在一切都很好!!!谢谢 。因此,根据返回的数据,我可以直接使用或映射到我需要的适当的 Observable。

    【讨论】:

    • 大声笑,为什么是 ?地图中的 .shows 属性已经具有所需的类型
    • 我尝试了上述方法。我在服务中获取数据,但在组件中没有。你能告诉我如何调用组件中的服务吗?提前谢谢
    【解决方案4】:

    .map(res=&gt; res['shows'] ) 成功了

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    • 是的更多关于为什么 res.shows 不起作用但它起作用的信息
    【解决方案5】:

    有两种方法可以做到这一点。您可以使用 .map 操作符形成 observable 将一种类型的 observable 映射到另一种类型的 observable 中,第二种方法包括仅在接口的帮助下。

    第一种方法(在.map 的帮助下)

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    import { Observable } from 'rxjs/Observable';
    
    import 'rxjs/add/operator/map';
    
    interface ItemsResponseObj {
        id: string,
        modified: string,
        name: string
    }
    
    interface ItemsResponse {
        shows: Array<ItemsResponseObj>;
    }
    
    @Injectable()
    export class AppService {
    
        constructor(private http: HttpClient) { }
    
        getData(): Observable<ItemsResponseObj[]> {
            return this.http.get<ItemsResponse>('api/api-data.json')
                .map(res => res.shows);
        }
    
    }
    

    第二种方法是借助包装接口

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    
    import { Observable } from 'rxjs/Observable';
    
    interface ItemsResponseObj {
        id: string,
        modified: string,
        name: string
    }
    
    interface ItemsResponse {
        shows: Array<ItemsResponseObj>;
    }
    
    @Injectable()
    export class AppService {
    
        constructor(private http: HttpClient) { }
    
        getData(): Observable<ItemsResponse> {
            return this.http.get<ItemsResponse>('api/api-data.json')
        }
    
    }
    

    【讨论】:

    • 创建一个新接口只是为了包装数据,然后解包它不是最好的方法
    猜你喜欢
    • 2018-12-14
    • 2019-09-30
    • 2018-07-25
    • 1970-01-01
    • 2021-12-30
    • 2020-02-10
    • 2012-01-23
    • 1970-01-01
    • 2017-04-23
    相关资源
    最近更新 更多