Recursive using expand() and concatMap() in Angular 7

前提是你 提交于 2019-12-06 09:49:03

问题


I have following API list below:

1. https://www.something.com/?filter=something

Result: 
{ 
  id: 12
  previous: null
  next: https://www.something.com/?filter=something&page=2
  data: ...
}

2. https://www.something.com/?filter=something&page=2

Result: 
{ 
  id: 13
  previous: https://www.something.com/?filter=something
  next: https://www.something.com/?filter=something&page=3
  data: ...
}

3. https://www.something.com/?filter=something&page=3

Result: 
{ 
  id: 14
  previous: https://www.something.com/?filter=something&page=2
  next: null
  data: ...
}

I want to loop through all of the urls after getting the data back of each API call, check if the next variable is null. If it is not null, it will keep continue going. while it's going through, the data of each API call will be concat and return to output.

This is what i have been trying so far

 getByURL(url: string): any {
    return this.apiService.get(url).pipe(map(data => data));
  }

  getData(): Observable<any> {
    const url = 'https://www.something.com/?filter=something';
    return this.getByURL(url).pipe(
      expand(({ data }) => {
        if (!data.next) return this.getByURL(data.next);
        else return empty();
      }),
      concatMap(({ content }) => {
        return of(content.data);
      })
    );
  }

But i got undefined result, i have struggled it for several day. Thanks

UPDATED

I put my code here in stackblitz: I have 3 api call :

http://5cf15627c936cb001450bd0a.mockapi.io/users
http://5cf15627c936cb001450bd0a.mockapi.io/users2
http://5cf15627c936cb001450bd0a.mockapi.io/users3

I want to gather all of the data after each requests. Please see the console to see the output. i always get undefined. Thanks

https://stackblitz.com/edit/angular-rai6az?file=src%2Fapp%2Fapp.component.ts


回答1:


I fixed your code as below (fixed stackblitz)

  ngOnInit() {
    this.getByPageNext()
      .subscribe(data => {
        console.log(data);
      });
  }

  get(url: string): Observable<any> {
    return this.httpClient
      .get(url)
      .pipe(catchError(this.formatErrors));
  }

  formatErrors(error: any) {
    console.error('error', error);
    return throwError(error.error);
  }

  getByURL(url: string): any {
    return this.get(url);
  }

  getByPageNext(): Observable<any> {
    const url = 'https://5cf15627c936cb001450bd0a.mockapi.io/users2';
    return this.getByURL(url)
      .pipe(
        expand((response: Array<any>) => {
          if (response && response.length && response[0].next) {
              return this.getByURL(response[0].next);
          }
          else {
            return empty()
          }
        }),
        map(obj => obj[0]), 
        reduce((acc, x: any) => acc.concat([x.data]), []),
      );
  }

so it will concat all data as array and recursive calling http works fine.

The only problem is when calling 'https://5cf15627c936cb001450bd0a.mockapi.io/users' the next url is http not https which will result in HttpError -> ProgressEvent.

So I started form 'https://5cf15627c936cb001450bd0a.mockapi.io/users2' and rest is working fine. So after you changed the backend to fix the next link, then change it back to your original request.

The other point was your result from api comes back as an array not an object, this is why I accesses result[0]

The other point was your condition to return empty() was vice versa



来源:https://stackoverflow.com/questions/56398014/recursive-using-expand-and-concatmap-in-angular-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!