【问题标题】:Multiple rxjs http requests Angular 6多个rxjs http请求Angular 6
【发布时间】:2018-07-24 16:09:28
【问题描述】:

我有以下代码:

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 循环迭代良好。 以前我尝试过相同的功能,但以递归方式。有同样的问题。

【问题讨论】:

  • 您需要使用例如订阅 Observable。 subscribe()

标签: rxjs angular6


【解决方案1】:

最好的方法是使用 flatMap 和 forkJoin 运算符创建一个表示您想要发出的所有请求的单个 observable。您的代码中的异步操作存在许多问题,这意味着返回的结果将不包括内部 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,当你订阅这个 observable 时,它​​也应该解决所有内部查询。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 对于“短命”的 observable(从 http 请求派生的那些是短命的),一旦 HTTP 请求完成,它们就会自行终止。对于“长期存在的”可观察对象(例如可以发出多个项目的对象,例如通知某种变化的服务),您必须取消订阅,或提供一些其他方法来终止可观察对象(操作符,如 takeWhile、takeUntil 等),当组件被销毁。
    猜你喜欢
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 2019-12-25
    相关资源
    最近更新 更多