22

When an async service has no return value but I want to use Observables I'm inclined to use Observable<boolean>. But I don't have meaning for this boolean value because the service either fails or succeeds and if it fails I want the Observable to be in the error state. This leaves only 'true' values for the observed boolean.

Is the following use of Observable<void> a good pattern for these situations? Or are there foreseeable problems with the use of Observable<void>

const asyncFuncWithoutResult = (): Observable<void> => {
  // fake something async that has no return value

  const itWorked = true; // or not
  if (itWorked) {
    return Observable.of();
  } else {
    return Observable.throw(Error('It did not work'));
  }
}

// call the service
asyncFuncWithoutResult()
  .subscribe(
    undefined, // nothing will be emitted when using Observable.of()
    (err: any) => console.error(err), // handle error state
    () => console.log('Success'),     // handle success state
  );
Halt
  • 2,924
  • 4
  • 22
  • 26
  • 1
    I can't see any obvious problems. If you encounter situations in which you need to emit an arbitrary value, you can always use `concat` and `Observable.of` to emit whatever value you want. E.g. `asyncFuncWithoutResult().concat(Observable.of("success!"))`. – cartant Sep 23 '17 at 12:43
  • Thx, that is a very useful tip. – Halt Sep 23 '17 at 15:01

1 Answers1

26

Just to be more precise, when you define a Subject with generic type void there are two ways you can call its next() method and that is without any argument:

const subject = new Subject<void>();
subject.next();

...or with void 0:

subject.next(void 0);

In fact, the value argument to next is optional so if you don't specify it it'll send undefined which means that even if you have Subject<void> you'll still receive next notifications:

asyncFuncWithoutResult().subscribe(alawaysUndefined => {
  /* ... */
});

Also note that you can turn any Observable into <void> (this is necessary when you want to merge multiple Observables) by map:

source.pipe(map(() => void 0))
   ...
Cel
  • 6,467
  • 8
  • 75
  • 110
martin
  • 93,354
  • 25
  • 191
  • 226
  • Thank you for your additional insight, very helpful. If subject.next(); results in an 'undefined' being emitted does it make sense that analogue to this Observable.of() does not return an Observable with one 'undefined' emitted? – Halt Sep 25 '17 at 18:11
  • 4
    I think these are two different things. It's perfectly fine to have an Observable that doesn't emit any `next` and only sends the `complete` notification, just like `Observable.of()` does (or `Observable.empty`). On the other hand it doesn't make sense to have `subject.next()` that does nothing because what's the point of calling this method when you know it won't do anything? For the same reason there's no Observable that wouldn't emit any `next`, `complete` or `error` notification because why would anyone want to use them. – martin Sep 25 '17 at 19:45