In some situations it is beneficial to force an observable to resolve subscriptions asynchronously, via use of the
observeOn operator. Failing that, it is at least possible to force an observable to resolve asynchronously. The issue from an Angular perspective is that we usually want our
subscribe callback to run in the Angular zone, otherwise change detection won't automatically kick off. Additionally, inside an asynchronous observer callback
setTimeout does not run in the app zone, eliminating a potentially obvious solution. To code defensively, one might use
NgZone.run wherever there's a possibility that an observable is async. Unfortunately, this has the knock-on effect of causing errors if the observable is not async. To prevent those errors observables can be uniformly forced async, with
NgZone used in the subscribe callback, resulting in uniform, proper behaviour. These measures have a not insubstantial technical cost.
I am not presently aware of a way to ensure that callbacks on async observables are wrapped in
NgZone except for manual use inside the callbacks themselves, pending further research. As such, a user's class might easily be the unwitting consumer of an async observable, and cannot reasonably expect to receive only synchronous observables. Additionally, even if there were such a mechanism, observables can be passed through and manipulated by several classes, only one of which is aware that the observable is asynchronous.
Problematically, NgZone is not readily available in all contexts, so far as I am aware. In particular, making it available to a free function is awkward, and making it available as part of a decorator (for use in a method added by that decorator, for example) is, absent a very hacky use of
platform, impossible. This currently has the unfortunate consequence of forcing significant amounts of defensive boilerplate into the user's code, rather than being handled behind the scenes.
Ideal solution: ZoneScheduler
We'd have to trust that an observable was scheduled using ZoneScheduler, but that's an acceptable risk considering how much defensive code it eliminates. Depending on the use case, there could still be a runtime check for whether we're executing in the Angular zone that could throw an exception if needed.