title: Resolving an observable inside `switchMap` in NGRX effect
body: <p>I'm caching some data using NGRX like this:</p>
  
  <pre><code>@Effect() public getProductList$ = this.actions$
      .pipe(
          ofType&lt;actionType&gt;(actions.ACTION_NAME),
          withLatestFrom(this.store.select(x =&gt; x.storeSlice), (action: any, store: any) =&gt; store.data),
          switchMap((data: any) =&gt; {
              if (data.items.length &gt; 0) {
                  return [new actions.Success(data.items)];
              }
  
              const localData: any[] = localStorage.getItem(...);
  
              if (localData != null) {
                  return [new actions.SuccessAction(localData)];
              }
              else {
                  return this.apiService.getAll()
                      .pipe(
                          map(result =&gt; new actions.Success(result)),
                          catchError(error =&gt; actions.Failure(error));
              }
          })
      );
  </code></pre>
  
  <p>Basically, I try to get the data from the store first, if the resulting array has items, I return a Success action with the data. Otherwise, I try to load the data from the <code>localStorage</code> and if it exists I return the success action with it. Finally, if there is no cached data, I call the API to get the data, and this can result in a Success or Failure action.</p>
  
  <p>The problem is that the data grew too much and I can't store it in the <code>localStorage</code> anymore, so I need to use <code>IndexedDb</code>, which works with promises.</p>
  
  <p>I created a wrapper service around the <code>IndexedDb api</code> and my method returns an <code>Observable</code> with the data. So I need to switch the <code>const localData: any[] = localStorage.getItem(...);</code> with my service call. With the <code>localStorage</code> everything is fine since it is synchronous, but the <code>IndexedDb</code> is not.</p>
  
  <p>I tried something like this, but it does not work:</p>
  
  <pre><code>@Effect() public getProductList$ = this.actions$
      .pipe(
          ofType&lt;actionType&gt;(actions.ACTION_NAME),
          withLatestFrom(this.store.select(x =&gt; x.storeSlice), (action: any, store: any) =&gt; store.data),
          switchMap((data: any) =&gt; {
              if (data.items.length &gt; 0) {
                  return [new actions.Success(data.items)];
              }
  
              return this.idb.getData().map(localData =&gt; {
                  if (localData != null) {
                      return [new actions.SuccessAction(localData)];
                  }
                  else {
                      return this.apiService.getAll()
                          .pipe(
                              map(result =&gt; new actions.Success(result)),
                              catchError(error =&gt; actions.Failure(error));
                  }
              });
  
  
          })
      );
  </code></pre>
  
  <p>This does not work because I'm returning an Observable instead of the actual <code>action</code>. But how could I extract the data out of the <code>Observable</code>? Is there an rxjs operator that could help me with this?</p>
  
  <hr>
  
  <p>If anyone gets here in future, this was the solution:</p>
  
  <pre><code>@Effect() public getProductList$ = this.actions$
      .pipe(
          ofType&lt;actionType&gt;(actions.ACTION_NAME),
          withLatestFrom(this.store.select(x =&gt; x.storeSlice), (action: any, store: any) =&gt; store.data),
          switchMap((data: any) =&gt; {
              if (data.items.length &gt; 0) {
                  return [new actions.Success(data.items)];
              }
  
              return this.idb.getData()
                  .pipe(
                      map(data =&gt; new actions.SuccessAction(data),
                      switchMap(successActionFromIDB =&gt; {
                          if (successActionFromIDB.payload.length &gt; 0) {
                              return of(successActionFromIDB);
                          }
                          else {
                              return this.apiService.getAll()
                                  .pipe(
                                      tap(data =&gt; this.idb.setData(data)),
                                      map(data =&gt; new actions.SuccessAction(data)),
                                      catchError(error =&gt; new actions.FailureAction(error))
                                  )
                          }
                      })
                  )
              );
          })
      );
  </code></pre>