3

I am attempting to make recursive http calls to Reddit's API using a value from the previous call. The problem is that the previous call is not finished before the next one starts, so duplicate calls are being made. The "after" value should be updated for every call until the "after" value is undefined. I found this related post and have attempted to use the solution described, but I can't figure out how to make sure the previous call is finished before making the next call. Below is my actual code:

private getSavedPostsForAuthenticatedUser(username: string, after: string, userPosts: any) {
    const headers = new Headers();
    if (!userPosts) {
        userPosts = [];
    }
    headers.append('Authorization', `Bearer ${this._token}`);
    const redditUrl = `${RetainerConfig.redditOauthUrl}user/${username}/saved`;
    const url = after ? `${redditUrl}/?after=${after}` : redditUrl;
    return this._http.get(url, { headers: headers })
        .map(response => response.json())
        .expand(response => {
            if (response.data) {
                for (const post of response.data.children) {
                    userPosts.push(post);
                }
                if (response.data.after) {
                    return this.getSavedPostsForAuthenticatedUser(username, response.data.after, userPosts);
                }
            }
            return Observable.of(userPosts);
        });
2
  • Perhaps part of the problem is that the project function you pass to expand never returns a empty observable. Without doing so, I cannot see how the expansion will cease. Commented Jul 8, 2017 at 3:20
  • This is correct. As noted in the accepted answer, I was also recursively calling the expand operator which caused inception-like problems. Commented Jul 9, 2017 at 11:47

1 Answer 1

10

Returning the same function getSavedPostsForAuthenticatedUser will cause recursive expands. To solve this you need to separate the http observable.

  private getSavedPostsForAuthenticatedUser(username: string, after: string, userPosts: any) {
    const request$ = this._getRequest(username, after, userPosts);
    if (!userPosts) {
      userPosts = [];
    }
    return request$
      .expand(response => {
        if (response.data) {
          for (const post of response.data.children) {
            userPosts.push(post);
          }
          if (response.data.after) {
            return this._getRequest(username, response.data.after, userPosts);
          }
        }
        return Observable.of(userPosts);
      });
  }

  private _getRequest(username: string, after: string) {
    const headers = new Headers();
    headers.append('Authorization', `Bearer ${this._token}`);
    const redditUrl = `${RetainerConfig.redditOauthUrl}user/${username}/saved`;
    const url = after ? `${redditUrl}/?after=${after}` : redditUrl;

    return this._http.get(url, {headers: headers})
      .map(response => response.json());
  }

To stop the expanding you may use Observable.empty(). Please refer to this post.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I've been stuck on this a while and this answer fixed my problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.