最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - RXJS while loop for pagination - Stack Overflow

programmeradmin4浏览0评论

I try to query all people data from the swap api. The URL swapi.co/api/people returns an object with an people array and the URL(swapi.co/api/people/?page=2) where I get the next data from. What I want to do is that the subscribe method updates the angular component every time a new page is available.

I’m new to the reactive programming model. How can I implement a while loop or a sequence of Observables?

This works for the first page:

getAllPeople(): Observable<Person[]> {
    let nextUrl = ;

    let source = Observable.create(observer => {

            this.http.get(nextUrl, { headers: this.headers })
            .map(response => {
                    let body = response.json();
                    nextUrl = body.next;
                    return nextUrl != null ? body.results as Person[] : null;
                }
            )
            .retry(5)//send same request based on the url of the previous request till the field next is null
            .catch(error => observer.error(error))
            .subscribe(persons => {
                    if (persons !== null) {
                        observer.next(persons)
                    }
                }
            );

        //observerplete();
    })


    return source;
}

Edit: I added the retry() method. I hope it is easier to understand what I intend to do. After the first request, it sends more requests to the same URL. Unfortunately, it doesn't use the new URL I get from the previous request.

/?page=1 -> /?page=2 -> /?page=3 -> null

I don’t know how many requests I need to retrieve all data.

I try to query all people data from the swap api. The URL swapi.co/api/people returns an object with an people array and the URL(swapi.co/api/people/?page=2) where I get the next data from. What I want to do is that the subscribe method updates the angular component every time a new page is available.

I’m new to the reactive programming model. How can I implement a while loop or a sequence of Observables?

This works for the first page:

getAllPeople(): Observable<Person[]> {
    let nextUrl = http://swapi.co/api;

    let source = Observable.create(observer => {

            this.http.get(nextUrl, { headers: this.headers })
            .map(response => {
                    let body = response.json();
                    nextUrl = body.next;
                    return nextUrl != null ? body.results as Person[] : null;
                }
            )
            .retry(5)//send same request based on the url of the previous request till the field next is null
            .catch(error => observer.error(error))
            .subscribe(persons => {
                    if (persons !== null) {
                        observer.next(persons)
                    }
                }
            );

        //observer.complete();
    })


    return source;
}

Edit: I added the retry() method. I hope it is easier to understand what I intend to do. After the first request, it sends more requests to the same URL. Unfortunately, it doesn't use the new URL I get from the previous request.

http://swapi.co/api/?page=1 -> http://swapi.co/api/?page=2 -> http://swapi.co/api/?page=3 -> null

I don’t know how many requests I need to retrieve all data.

Share Improve this question edited Sep 18, 2018 at 3:21 Patrick asked May 21, 2017 at 13:05 PatrickPatrick 4478 silver badges17 bronze badges 4
  • you probably need to use websockets to get notifications about new pages. – Julia Passynkova Commented May 21, 2017 at 14:44
  • I’m not familiar with websockets but I think it is not what I need. The response of an http get request to the server tells me where to get the next data. – Patrick Commented May 21, 2017 at 15:05
  • sure, if you just need to get all pages - you don't need it but your question was to be able to update "every time a new page is available." – Julia Passynkova Commented May 21, 2017 at 15:33
  • Sorry for my bad expression. The code above is a service method. An ng component is the observer. The component should be notified(observer.next()) each time a page(part of the data) is downloaded – Patrick Commented May 21, 2017 at 15:39
Add a comment  | 

2 Answers 2

Reset to default 22

By using the expand operator you can create a new Observable sequence for each value that is returned. To stop the expand from creating any new sequences, once we get a next URL that is null, we can return an empty Observable to stop expanding our sequences. Finally, we can use a reduce operator to aggregate the different pages of data into one array that we then emit back to the original subscriber. This can be accomplished as follows:

public getAllPeople(): Observable<Person[]> {
    return Observable.create(observer => {
          this.getPage("http://swapi.co/api/people/")
            .expand((data, i) => {
                return data.next ? this.getPage(data.next) : Observable.empty();
            })
            .reduce((acc, data) => {
                return acc.concat(data.results);
              }, [])
            .catch(error => observer.error(error))
            .subscribe((people) => {
                  observer.next(people);
                  observer.complete();
            });
    });
}

private getPage(url: string): Observable<{next: string, results: Person[]}> {
  return this.http.get(url, { headers: this.headers })
            .map(response => {
                    let body = response.json();
                    return {
                      next: body.next,
                      results: body.results as Person[]
                    };
                }
            );
}

Demo

Use expand operator like:

function getData(id) {
   let next = id<5 ? id+1 : null;
   let obj = {id:id, next:next}
   return next ?   Rx.Observable.of(obj) : Rx.Observable.empty();
 }

 getData(0)
   .expand(el=> getData(el.next))
   .subscribe(x=>console.log(x));
发布评论

评论列表(0)

  1. 暂无评论