2

I have an endpoint that retrieves all the comments for a post and in that list there's the user_id property for each comment so from that I make another call that retrieves the user information such as name or email. This is what I've implemented using forkJoin and flatMap.

getCommentsList() {
    return this.http.get("COMMENTS_ENDPOINT")
        .map(res => res.json())
        .flatMap(comments => Observable.forkJoin(comments.map(comment => this.getUserDetail(comment.user_id)
            .map(user => (comment.user = user, comment))))));
}

getUserDetail(id) {
    return this.http.get("USER_ENDPOINT/id")
        .map(res => res.json());
}

Although this works fine, duplicate calls to user endpoint get made when there's the same user commenting more than once. How can I store the user data and use it when the same user data is to be retrived? I have tried

storedUsers:any = {};

getUserDetail(id) {
    if (this.storedUsers[id]) {
        console.log("using cache");
        return Observable.of(this.storedUsers[id]);
    }
    return this.http.get("USER_ENDPOINT/id")
        .map(res => res.json())
        .do(user => this.storedUsers[user.id] = user);
}

But never in console it logs using cache.

Megh Gandhi
  • 103
  • 1
  • 8

2 Answers2

0

My take is that it might be because the cache store is not defined on the level you are trying to access it. The function you are calling is outside the level where this.store is.

Try to pass the store to the callback function like this:

... => this.getUserDetail(comment.user_id, this.storedUsers)

and use the passed reference:

getUserDetail(id, storedUsers) {
    if (storedUsers[id]) {
    ...
ForestG
  • 17,538
  • 14
  • 52
  • 86
0

I think it is actually because the http request has not completed yet before the subsequent calls to getUserDetail are called.

I would recommend you read through this SO question to get some ideas around how to cache the result of http call.

If you use that in conjunction with your storedUsers dictionary you should get the behavior you want, with a minor change. Instead of storing the result of the http request, instead store the cached http request and return that.

Here is a quick potential example showing what I'm trying to say:

storedUsers:{ [id: number]: Observable<User> } = {};

getUserDetail(id) {
    if (!this.storedUsers[id]) {
        this.storedUsers[id] = this.http.get("USER_ENDPOINT/id")
            .map(res => res.json())
            .shareReplay(1);
    }

    return this.storedUsers[id];
}
Daniel W Strimpel
  • 8,190
  • 2
  • 28
  • 38