1

I have an observable const numbers = from([1,2,3]) which will emit 1, 2, 3, then complete.

I need to map this to another observable e.g. like this:

const mapped = numbers.pipe(
   concatMap(number => Observable.create(observer => {
     observer.next(number);
   }))
 );

But now the resulting observable mapped emits 1, 2, 3 but not the complete event.

How can I preserve the complete event in mapped?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Will Hardwick-Smith
  • 969
  • 3
  • 13
  • 24

1 Answers1

2

Your code gives me just "1" (with RxJS 6); are you sure you see 3 values?

Rx.from([1,2,3]).pipe(
   op.concatMap(number => Rx.Observable.create(observer => {
     observer.next(number);
   }))
 ).forEach(x => console.log(x)).then(() => console.log('done'))

You're never completing the created Observable (it emits one value but never calls observer.complete()). This works:

Rx.from([1,2,3]).pipe(
   op.concatMap(number => Rx.Observable.create(observer => {
     observer.next(number); observer.complete();
   }))
 ).forEach(x => console.log(x)).then(() => console.log('done'))

This all shows how hard it is to use Rx.Observable.create() correctly. The point of using Rx is to write your code using higher-level abstractions. A large part of this is preferring to use operators in preference to observers. E.g. in your case (which is admittedly simple):

Rx.from([1,2,3])
  .pipe(op.concatMap(number => Rx.of(number)))
  .forEach(x => console.log(x)).then(() => console.log('done'))
ariels
  • 545
  • 4
  • 17
  • You're right. I made that example using `Observable.create` to replace the complex situation I was working with but didn't bother to check it. I'm having a look my original situation to see if I can find out what was happening – Will Hardwick-Smith Feb 27 '19 at 01:17
  • I think that the problem may have been that originally my `concatMap` returned an observable that would sometimes never emit anything (with `observer.next`) – Will Hardwick-Smith Feb 27 '19 at 01:25