Should an Angular service have state?

testing123 picture testing123 · Jan 9, 2013 · Viewed 12.3k times · Source

Recently some co-workers and I were having a discussion as to whether or not AngularJS services should have state or not. We came up with some arguments for and against it and I wanted to get additional thoughts and feedback on the subject. In my searching I found this but there doesn't seem to be any clear best-practice mentioned. In the none client-side world a service should never hold state, but I am starting to think that it might be acceptable client-side because its a different problem.

Reasons for services holding state:

  1. The service isn't going to be accessed by multiple threads. Each browser will have its own instance of the service.
  2. Allows the service to hold the state only it cares about instead of storing it in the rootScope. encapsulates

Reasons for services to not hold state:

  1. Services are no longer idempotent. Calling functions may change state and therefore may have different results when calling it based upon the state of the service.
  2. I would think that overall this would be easier to test.

One way that might address #2 in the "for services holding state" section would be to have an appState object set on the rootScope that contains the current state of the application. Then all the state would be gathered in one location and then you just pull what you need out of it in your service. I found this and wondered

Answer

Josh David Miller picture Josh David Miller · Jan 9, 2013

It would probably depend on what you mean by "state", but in many cases I think the answer would be yes: services should hold state.

For example, if you have a service that is responsible for communication with an API, that service could hold the authentication state.

By the way, I'm not sure how much idempotence matters for AngularJS services - they're singletons and so inherently have some state. You could (and in some cases must) create idempotent methods on the service, but that's a separate issue.