WIP: refactoring after review with Igor

We are not going to expose promises from this service for now since it
is not a common use case and it is easier to add them in later than to
remove them if they cause problems.  Moreover it makes the code considerable
simpler.

The code will implicitly call $apply if it calls the wrapped function
asynchronously, as it is inside the $timeout handler.  The code will
not explicitly call $apply if it is calling the wrapped function
synchronously (i.e. if `immediate` is `true`) - we will leave it up to
the calling environment to control that.  In most cases the caller will
already be in an apply block.