What are "decorators" and how are they used?
decorator
can intercept service instance created by factory, service, value, provider
, and gives the options to change some instance(service)
that is otherwise not configurable / with options.
It can also provide mock up instances for testing purpose, for example $http
.
A good use case of $provide.decorator
is when you need to do minor "tweak" on some third-party/upstream service, on which your module depends, while leaving the service intact (because you are not the owner/maintainer of the service). Here is a demonstration on plunkr.
Decorators allow us to separate out cross-cutting concerns and allow services to preserve the single-responsibility-principle without worrying about "infrastructure" code.
Practical uses of decorators:
- Caching: if we have a service which makes potentially expensive HTTP calls, we can wrap the service in a caching decorator which checks local storage before making the external call.
- Debugging/Tracing: have a switch depending on your development/production configuration which decorates your services with debugging or tracing wrappers.
- Throttling : wrap frequently triggered calls in a debouncing wrapper. Allows us to easily interact with rate-limited services, for example.
In all these cases, we limit the code in the service to its main responsibility.