Loop array and return data for each id in Observable

前端 未结 2 783
旧时难觅i
旧时难觅i 2020-12-25 08:46

Using RxJS v6 is challenging to retrieve data from sub collection for every item in the loop. There is no way to iterate throw array that is retrieved from HTTP call. Merge

相关标签:
2条回答
  • 2020-12-25 09:24

    This is quite possible using nested mergeMap and map. A key approach to stick with Observable is expanding the contacts array into an observable using from function. Then you collect the data using toArray operator. Providing documented example:

    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 
                  (original, detail) => ({...original, relationship: detail})
                ),
                // collect all contacts into an array
                toArray(),
                // add the newly fetched data to original result
                map(contact => ({ ...result, contact})),
              )
            ),
        );
    }
    

    Edit: result selector is deprecated

    In the inner mergeMap, you can use a map afterwards.

    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).pipe(
                  map(detail => ({ ...contact, relationship: detail })),
                ),
              // collect all contacts into an array
              toArray(),
              // add the newly fetched data to original result
              map(contact => ({ ...result, contact })),
            ),
          ),
        ),
      );
    }
    
    0 讨论(0)
  • 2020-12-25 09:37

    Although kvetis's answer can work for you here is what I implemented, just posting it because I found it interesting to solve.

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

    Here is an example solution for your question, I have made dummy Observables. https://stackblitz.com/edit/angular-tonn5q?file=src%2Fapp%2Fapi-calls.service.ts

    0 讨论(0)
提交回复
热议问题