2

I'm working with @ngrx/store and I'm displaying notification when request starts or returns an error and hiding it if request is successful. It works as intended, and I wanted to delay initial notification so it's not shown if request ends quickly. I've tried several Observable/Subject operators that work with time:

  • With delay and bufferTime message is null which causes an error in <notification>
  • Using debounceTime doesn't show initial message, but with slow responses and errors message is still null
  • throttleTime only shows initial notification and hides it with slow responses

Without any of these *ngIf="(notification |async)" does it's job and message is set only if notification isn't null.

I suppose I could just hide <notification> with CSS transition delay, but I was wondering if anyone knows other way to solve this...

@Component({
  template: `<notification [message]="notification |async" *ngIf="(notification |async)"></notification>`
})
export class RootRoute {
  constructor(...) {
    this.notification = this.store.select('notification')
      // None of these solve my issue:
      // .delay(250)
      // .throttleTime(250)
      // .debounceTime(250)
      // .bufferTime(250)
  }
}

export class Service {

  private request(method: any, values: any, endpointsUrl: string, actionType: string, storeSelector?) {
    this.store.dispatch({ type: "SHOW_NOTIFICATION", payload: {code: 200, message: "Getting data from server..."} });

    this._http.request(BASE_URL + endpointsUrl, { body: JSON.stringify(values), method: method })
      .map(response => response.json())
      .map(payload => ({ type: actionType, payload }))
      .subscribe({
        next: action => this.store.dispatch(action),
        error: payload => this.store.dispatch({ type: 'API_ERROR', payload }),
        complete: () => this.store.dispatch({ type: "HIDE_NOTIFICATION" })
      });

    if (storeSelector)
      return this.store.select(storeSelector);
  }

}
Sasxa
  • 40,334
  • 16
  • 88
  • 102
  • Have you tried [`timeInterval()`](http://reactivex.io/documentation/operators/timeinterval.html) ? – Langley Feb 15 '16 at 15:44
  • @Langley Not sure how would I use it in this case. Also it seams it's not a valid operator for `Subject`... – Sasxa Feb 15 '16 at 15:56
  • You mentioned `Observable` not `Subject`, `Subject` wraps an observable though so it might have it too or something similar. It helps to specify a time the observable will call its subscribers, I thought that's what you meant by "I wanted to delay initial notification so it's not shown if request ends quickly" – Langley Feb 15 '16 at 16:00
  • `@ngrx/store.select()` returns Subject, I'll update the question... – Sasxa Feb 15 '16 at 16:10

2 Answers2

1

I ended up with:

this.store.select('notification')
  .debounceTime(250)
  .subscribe((message: INotification) => this.notification = message);

and reverted back to ChangeDetectionStrategy.Default for this component. I guess it's one of the issues with async pipe...

Sasxa
  • 40,334
  • 16
  • 88
  • 102
0

Your question makes me think about another one:

I didn't test but mixing flatMap, delay and takeUntil operators could correspond to your needs.

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360