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.