循环数组并为Observable

时间:2019-04-04 13:03:51

标签: angular rxjs observable angular7 rxjs6

使用RxJS v6很难从子集合中检索循环中每个项目的数据。无法迭代从HTTP调用检索的throw数组。合并映射仅对需要在所有数组项目上执行的单个项目执行此操作。

我已经坚持了3天。我已经尝试了一切。问题在于,新的管道语法在为您提供组织代码的巧妙方法的同时,没有简单的方法来循环引发数据收集。无法使用地图javascript函数,因为它在可观察范围之外并且返回的项目不确定。在互联网上,我只能找到一个很好的单个mergeMap的基本示例。但是我需要使用 带有http调用的数组中的每个项目,并将响应附加到同一对象。

我从无法控制的第三方的两个端点开始。我嘲笑了一些示例API来说明。

端点1-返回所有项目ID: http://localhost:3000/contact

{
  "name": "test",
  "contact": [
    {
      "_id": "5c9dda9aca9c171d6ba4b87e"
    },
    {
      "_id": "5c9ddb82ca9c171d6ba4b87f"
    },
    {
      "_id": "5c9ddb8aca9c171d6ba4b880"
    }
  ]
}

端点2-返回单个项目信息: http://localhost:3000/contact/5c9dda9aca9c171d6ba4b87e

[
   {
     "_id": "5c9dda9aca9c171d6ba4b87e",
     "firstName": "Luke",
     "lastName": "Test",
     "email": "vgadgf@adsgasdg.com",
     "created_date": "2019-03-29T08:43:06.344Z"
   }
]

期望的结果-通过使用RxJs v6 +返回可观察到的嵌套数据:

{
  "name": "test",
  "contact": [
    {
      "_id": "5c9dda9aca9c171d6ba4b87e".
      "relationship":  {
                         "_id": "5c9dda9aca9c171d6ba4b87e",
                         "firstName": "Luke",
                         "lastName": "Test",
                         "email": "vgadgf@adsgasdg.com",
                         "created_date": "2019-03-29T08:43:06.344Z"
                       }
    },
    {
      "_id": "5c9ddb82ca9c171d6ba4b87f",
      "relationship": {
                         "_id": "5c9ddb82ca9c171d6ba4b87f",
                         "firstName": "Name2",
                         "lastName": "Test2",
                         "email": "vgadgf@adsgasdg2.com",
                         "created_date": "2019-03-29T08:43:06.344Z"
                       }
    },
    {
      "_id": "5c9ddb8aca9c171d6ba4b880",
      "relationship": {
                         "_id": "5c9ddb8aca9c171d6ba4b880",
                         "firstName": "Name3",
                         "lastName": "Test3",
                         "email": "vgadgf@adsgasdg3.com",
                         "created_date": "2019-03-29T08:43:06.344Z"
                       }
    }
  ]
}

当尝试使用Javascript循环时,我只是遇到错误,而使用不同的运算符也不能给我太多,因为RxJ中的循环存在问题。这是我产生的代码。请提供任何有用的建议或文档。

testService.service.ts

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {concatMap, map, mergeMap} from 'rxjs/operators';

@Injectable()
export class TestServiceService {

  constructor(
    private http: HttpClient
  ) { }

  public getCombinedData(): Observable<any> {
    return this.getMultipleRelationData()
      .pipe(
        map((result: any) => {
          result = result.contact;

          return result;
        }),
        mergeMap((fullResults: any) => {
          return fullResults[0].relationship = this.getSingleData(fullResults[0]._id);
        })
      );
  }

  public getSingleData(id): Observable<any> {
    return this.http.get('http://localhost:3000/contact/' + id);
  }

  public getMultipleRelationData(): Observable<any> {
    return this.http.get('http://localhost:3000/contact');
  }

}

我当前的最终数据看起来只是一个项目。如果我只想打一个电话,那就太好了...但是,它与上述所需的输出相差甚远。

  [
  {
    "_id": "5c9dda9aca9c171d6ba4b87e",
    "firstName": "Luke",
    "lastName": "Test",
    "email": "vgadgf@adsgasdg.com",
    "__v": 0,
    "created_date": "2019-03-29T08:43:06.344Z"
  }
]

2 个答案:

答案 0 :(得分:2)

使用嵌套的mergeMapmap很有可能。坚持使用Observable的一种关键方法是使用from函数将Contacts数组扩展为Observable。然后,您使用toArray运算符收集数据。提供记录的示例:

public getCombinedData(): Observable<any> {
    return this.getMultipleRelationData()
      .pipe(
        mergeMap((result: any) => 

          // `from` emits each contact separately 
          from(result.contact).pipe(
            // load each contact
            mergeMap(
              contact => this.getSignleData(contact._id),
              // in result selector, connect fetched detail data
              (original, detail) => ({...original, relationship: detail})
            ),
            // collect all contacts into an array
            toArray(),
            // add the newly fetched data to original result
            map(contact => ({ ...result, contact})),
          )
        ),
    );
}

答案 1 :(得分:0)

尽管kvetis的答案可以为您解决,但这是我实现的,只是发布它是因为我觉得解决起来很有趣。

  public getCombinedData(): Observable<any> {
    return this.getMultipleRelationData()
      .pipe(
        mergeMap((result: any) => {
          let allIds = result.contact.map(id => this.getSingleData(id._id));
          return forkJoin(...allIds).pipe(
            map((idDataArray) => {
              result.contact.forEach((eachContact, index) => {
                eachContact.relationship = idDataArray[index];
              })
              return result;
            })
          )
        })
      );
  }

这是您问题的示例解决方案,我制作了虚拟的Observables。 https://stackblitz.com/edit/angular-tonn5q?file=src%2Fapp%2Fapi-calls.service.ts