多个rxjs http请求Angular 6

时间:2018-07-24 16:09:29

标签: rxjs angular6

我有以下代码:

private getUsers(page, result) {
result = result||[];
return this.http.get(API_URL + '/users?page=1')
.pipe(map(response => {
  const response_filter = response.json();
  const users = response_filter['data'];
  const pages = response_filter['total_pages'];
  Array.prototype.push.apply(result, users.map((user) => new User(user)));
  while (page != pages)
  {
    this.http.get(API_URL + '/users?page=' + page)
    .pipe(map(resp => {
      console.log('test');
      const response_filter = resp.json();
      const users = response_filter['data'];
      Array.prototype.push.apply(result, users.map((user) => new User(user)));
      return result;
    }))
    .pipe(catchError(val => of(`Caught inner error: ${val}`)));
    page += 1;
  }
  return result;
}))
.pipe(catchError(val => of(`Caught error: ${val}`)));
}

代码在console.log('test')之前有效。该日志不会显示,但是while循环可以很好地进行迭代。 以前我尝试过相同的功能,但是以递归的方式。有同样的问题。

2 个答案:

答案 0 :(得分:0)

执行此操作的最佳方法是使用flatMap和forkJoin运算符创建一个表示您要发出的所有请求的可观察对象。代码中的异步操作存在很多问题,这意味着返回的结果将不包括内部HTTP请求的结果。

我将提出以下建议:

private getUsers(page, result) {
    return this.http.get(API_URL + '/users?page=1')
    .pipe(
        flatMap((response) => {
            const response_filter = response.json();
            const users = response_filter['data'];
            const pages = response_filter['total_pages'];
            let firstPageUsers: User[] = users.map((user) => new User(user));
            let getAllUsers: Observable<User[]>[];
            getAllUsers.push(of(firstPageUsers));
            while (page < pages)
            {
                getAllUsers.push(this.http.get(API_URL + '/users?page=' + page)
                   .pipe(
                       map(resp => {
                           console.log('test');
                           const response_filter = resp.json();
                           const users = response_filter['data'];
                           return users.map((user) => new User(user));
                       }),
                       // You need to decide if this is how you want errors
                       // handled, it doesn't seem too sensible to me:
                       catchError((err) => {
                           console.log(`Caught inner error: ${err}`);
                           return of([]); // needs to return type Observable<User[]>
                       })
                   )
                );
                page += 1;
            }
            return forkJoin(getAllUsers);
        }),
        map((allResponses) => {
            // allResponses will be an array of User arrays from 
            // all of the observables within the forkJoin, so now
            // we can iterate over all of those to create a single 
            // array containing all of the results.
            result = result||[];
            allResponses.forEach((responseUsers) => {
                 Array.prototype.push.apply(result, responseUsers);
            });
            return result;
        }),
        catchError((err) => {
            console.log(`Caught outer error: ${err}`);
            of(null); // Or whatever - again, think about your error cases.
        })
     );
  }

现在无论您在哪里调用getUsers,当您订阅此可观察对象时,它也应解析所有内部查询。

答案 1 :(得分:0)

Marks的答案很好,但是我已经使用Martin注释(使用subscription)解决了我的问题(也许不是很好,但是解决了)。首先,我订阅“获取页面计数”请求,然后在while循环中订阅“获取用户”请求。

我是新手,所以也许有人会回答一个问题“我必须在这里取消订阅吗?”

this._dataSub0 = this.userDataService.getPages().subscribe((pages) => {
  var page_num = pages;
  var i = 1;
  while (i < page_num) {
    this._dataSub = this.userDataService
      .getAllUsers()
      .subscribe(
        (users) => {
            for (let us of users) {
              this.users.push(us);
            }
        }
      );
    i++;
  }
});

public getAllUsers(page): Observable<User[]> {
return this.getUsers(page);
}
private getUsers(page) {
  var result = result||[];
  return this.http.get(API_URL + '/users?page=' + page)
  .pipe(map(response => {
    const response_filter = response.json();
    const users = response_filter['data'];
    const pages = response_filter['total_pages']
    if(pages == page)
      return null;
    Array.prototype.push.apply(result, users.map((user) => new User(user)));
    return result;
  }))
  .pipe(catchError(val => of(`Caught error: ${val}`)));
}
public getPages(): Observable<number> {
  var result;
  return this.http.get(API_URL + '/users?page=0')
  .pipe(map(response => {
    const response_filter = response.json();
    const pages = response_filter['total_pages']
    return pages;
  }))
  .pipe(catchError(val => of(`Caught error: ${val}`)));
}