Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

switchMap does not seem to complete when the inner observable completes

Tags:

rxjs

rxjs5

I'm still a noob when it comes to RxJS but here's a JSBin of what I am trying to do.

https://jsbin.com/wusalibiyu/1/edit?js,console

I have an observable 'a' (in my case it's the current active connection) which emits a new object whenever the connection reconnects. It's an observable itself because it can re-emit a new value.

I now want an observable that completes whenever an action is executed on the current connection. That action notifies it is done when the observable for it completes. This is b.

The problem is that when the inner observable completes, the outer does not complete. How to make the outer observable complete ... . Is there a different operator I should be using in RxJS5?

like image 209
SpoBo Avatar asked Nov 15 '16 13:11

SpoBo


1 Answers

If I understand your requirement correctly, you can "lift" the inner stream out using a materialize/dematerialize pair (note I refactored as well as part of my never ending war to get people to stop using Observable#create).

JsBin (excerpt below)

function b(a) {
  // Emit and complete after 100 millis
  return Rx.Observable.timer(100)

    // Ignore any values emitted
    .ignoreElements()

    // Emit the value on start
    .startWith(a)
    .do(() => console.log('creating observable'))
    .finally(() => console.log('b done'));
}

var a$ = Rx.Observable.from(['a', 'b'])
  .finally(() => console.log('a done'));

var result$ = a$.switchMap(function(a) {
  console.log('switching map for a to b', a);

  // This "materializes" the stream, essentially it maps complete -> next
  return b(a).materialize();
})
// This does the opposite, and converts complete events back, 
// but since we are now in the outer stream
// this results in the outer stream completing as well.
.dematerialize()
.share();


result$.subscribe(function(value) {
  console.log('value', value);
}, function(e) {
  console.error('e', e);
}, function() {
  console.log('completed!');
})

result$.toPromise().then(function(data) {
  console.log('this should trigger!?', data);
}, function(e) {
  console.error('boom', e.toString());
});
like image 94
paulpdaniels Avatar answered Sep 28 '22 08:09

paulpdaniels