1

I get the whole menu from the web service, which is huge. It has > 10000 items. Firstly, I wanted to do request, based on what the user clicked, but since it's a menu, there'll be a lot of clicking and a lot of requests. So I figured, that it's best to just load the complete structure and then query that huge json, based on needs.

The idea was that when I firstly call the service, it checks if it has any data. If it doesn't, the http request gets made and the data mapped to a variable in service. Then when I need subcategories or whatever, I query that data and I don't need to make hundreds of http request JUST for the menu. But, I feel that I haven't done this well. It works, but it seems hacky. Especially the part where I expect that the data is present (see the getSubCategories method below). Here's the code and please, feel free to notify me if there are any serious issues or provide ideas for making the code better:

  getMainCategories() {
    if (this.dataStore.length > 0) {

      return of(this.generateMainCategories(this.dataStore));
    } else

      if (this.observable) {

        return this.observable;
      } else {

        this.observable = this.http.get<ICategory[]>(`${this.apiUrl}/categories`).pipe(
          tap(() => {

            console.log('"getCategories" service called.');
          }),
          map((data) => {

            this.observable = null;
            this.dataStore = data;
            return this.generateMainCategories(this.dataStore);
          })
        ).share();
        return this.observable;
      }
  }

  getSubCategories(_id: string) {
    if (this.dataStore.length > 0) {

      return of(this.dataStore.find(x => x.TermCategoryUrl === _id));
    } else {

      return this.getMainCategories().pipe(

        map((data) => {

          return this.dataStore.find(x => x.TermCategoryUrl === _id);
        })
      );
    }
  }
uglycode
  • 3,022
  • 6
  • 29
  • 55
  • Maybe you could make use of `.publishReplay(1).refCount()`. There are a number of posts on SO about caching with rxjs like this one: https://stackoverflow.com/questions/42189801/rxjs-5-publishreplay-refcount – bygrace Dec 12 '17 at 15:10
  • I don't see how that would be helpful since i don't even make direct http requests, but reuse local data? – uglycode Dec 12 '17 at 15:17
  • With this approach you would create the observable upon construction, store it as a private class property, and return it with each method invocation. Upon the first subscribe it would hit the rest api to get the data. All subsequent subscribes would get the data retrieved from the api. So rxjs would handle keeping the local copy. – bygrace Dec 12 '17 at 15:23
  • That sounds great but how would i be able to manipulate the data from the local observable? Can you provide a simple example on how to change the data from local observable? – uglycode Dec 12 '17 at 15:26
  • Ah, good to know. Didn't realize that you wanted to modify the returned data. Have you considered using ngrx for this? – bygrace Dec 12 '17 at 15:37
  • I'm not very familiar with it, but afaik it'd be useful. Very useful. Basically i think this is the textbook example of why to use ngrx, i guess. But i don't even know where to start – uglycode Dec 12 '17 at 15:44
  • If you want to learn more then here is a good guide (https://gist.github.com/btroncone/a6e4347326749f938510) and checkout the docs and example app linked from here (https://github.com/ngrx/platform). – bygrace Dec 12 '17 at 15:48

0 Answers0