循环数组并返回Observable中每个id的数据

问题描述 投票:1回答:2

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

我被困在这3天了。我已经尝试了一切。问题是新的管道语法虽然为您提供了整理组织代码的简洁方法,但是没有简单的方法来循环抛出数据集合。使用map javascript函数是不可能的,因为它在observable之外,并且返回的项是未定义的。在互联网上,我只能找到一个合适的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": "[email protected]",
     "created_date": "2019-03-29T08:43:06.344Z"
   }
]

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

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

我只是在尝试使用Javascript循环时遇到错误并且使用不同的运算符并不会给我带来太多问题,因为RxJs中存在循环问题。这是我制作的代码。请提供任何有用的建议或文件。

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": "[email protected]",
    "__v": 0,
    "created_date": "2019-03-29T08:43:06.344Z"
  }
]
angular rxjs observable angular7 rxjs6
2个回答
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})),
          )
        ),
    );
}

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

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

© www.soinside.com 2019 - 2024. All rights reserved.