Postpone observable when other one fired in RxJs

2019-09-14 06:12发布

I have a table on a page and two subscriptions:

  1. First one reloads table data. It has a delay because it calls an api.
  2. Second highlights data. Does not affect table data.

When subscriptions fire one by one everything is OK, but when they fire at the same time data is highlighted and soon after is reloaded so highlighting is gone.

You can see it here.

Is there are way to postpone highlighting if reloading is in action?

Probably I can accomplish this by introducing loading variable but I am looking for reactiveX solution.

Thanks in advance.

1条回答
叼着烟拽天下
2楼-- · 2019-09-14 06:58

Keep in mind that in rxjs everything is a stream, which you can use to your advantage, I've modified you fiddle a bit so that everything is a stream now:

  var pageClicks = Rx.Observable.fromEvent(document.getElementById('page'),  'click');
  var highlightClicks = Rx.Observable.fromEvent(document.getElementById('highlight'), 'click');
  var bothClicks = Rx.Observable.fromEvent(document.getElementById('both'), 'click');

  var page = 0;
  var nextPage$ = Rx.Observable.of(page)
    .map(function() {
      page = (page + 1) % 2;
      return page
    })
    .switchMap(loadData)
    .do(renderData);

  var doBoth$ = nextPage$
    .do(highlight);

  // initial rendering of data
  doBoth$.subscribe();

  pageClicks
    .switchMapTo(nextPage$)
    .subscribe();

  highlightClicks
    .do(highlight)
    .subscribe();

  bothClicks
    .switchMapTo(doBoth$)
    .subscribe();

Here is the link to the updated fiddle: https://fiddle.jshell.net/r2L7k0mc/3/


Based on your comments I have updated your fiddle with the following code:

  var page$ = events.page$.share();
  var loadData$ = page$
    .startWith(0)
    .switchMap(page => loadData(page).takeUntil(page$))
    .do(renderData);
  loadData$.subscribe();

  var loading$ = Rx.Observable.merge(
    page$.mapTo(true),
    loadData$.mapTo(false)
  )
    .startWith(false)
    .publishReplay(1);
  loading$.connect();

  events.highlight$
    .switchMap(function() {
        return loading$
        .filter(function(isLoading) { return !isLoading; })
        .take(1);
    })
    .do(highlight)
    .subscribe();

See: https://fiddle.jshell.net/mc8h52r7/5/

However I would strongly suggest to rethink the architecture, since this is a very ugly set of streams, that could surely be optimized with a different architecture.

查看更多
登录 后发表回答