intermediate18 min

Services and Factories

AngularJS's .service() and .factory() for sharing logic, and its dependency injection.

What you'll learn

  • Distinguish .service() and .factory() as two ways to register shared logic
  • Explain how AngularJS's dependency injection identifies which service to inject by argument name
  • Read an existing service/factory registration and identify what it provides

Explanation

AngularJS offers two common ways to register shared, injectable logic. .service("name", function() { this.doSomething = () => {...}; }) registers a constructor function -- AngularJS creates one instance with new, and whatever you attach to this becomes the service's public interface. .factory("name", function() { return { doSomething: () => {...} }; }) registers a factory function -- AngularJS calls it once and uses whatever it returns as the service's value, giving you more flexibility (e.g. returning a plain object, a function, or anything else) than .service()'s "always a new-constructed instance" model.

AngularJS's dependency injection identifies what to inject by matching a function parameter's name to a registered service/factory name: app.controller("MainController", function(myDataService) { ... }) automatically receives the registered myDataService. This name-matching approach is convenient but has a real, well-known downside: minifying JavaScript typically renames function parameters, which breaks this name-based injection unless you use one of AngularJS's explicit-annotation workarounds (an array syntax listing dependency names as strings, or an $inject property) -- a genuine, historically significant gotcha when deploying minified AngularJS code, and something you may well encounter explained (or, worse, NOT explained and silently broken) in existing production code.

Guided lab

Predict: .service() vs .factory()'s resulting shape

AngularJSNot executed
This lab does not run in your browser or on VisaSparkSchools's servers. Read the code, predict what it does, then reveal the real expected output.

This models the difference between AngularJS's .service() (constructed with new) and .factory() (returns an explicit value). Predict what each produces.

// Modeling .service(): AngularJS calls "new ServiceFn()"
function GreeterService() {
  this.greet = (name) => `Hello, ${name}! (from service)`;
}
const serviceInstance = new GreeterService();

// Modeling .factory(): AngularJS calls "FactoryFn()" and uses its return value
function greeterFactory() {
  return {
    greet: (name) => `Hello, ${name}! (from factory)`,
  };
}
const factoryInstance = greeterFactory();

console.log(serviceInstance.greet("Ada"));
console.log(factoryInstance.greet("Grace"));

Stuck? Get a hint.

Common mistakes

  • Assuming .service() and .factory() are interchangeable with identical behavior -- .service() always constructs with new, .factory() returns whatever value you explicitly return.
  • Not recognizing that AngularJS's name-based dependency injection breaks under minification unless explicitly annotated (array syntax or $inject) -- a classic, real production bug.
  • Registering a service/factory but forgetting it must actually be listed as a parameter (by matching name) wherever it's meant to be injected.

Knowledge check

Knowledge check

1. How does .service() determine the service's public value?
2. How does AngularJS's dependency injection decide what to inject into a function?
3. Why can minification break AngularJS's default dependency injection?

Takeaway

Name-based dependency injection is convenient but breaks under minification without explicit annotation -- a real, historically significant AngularJS gotcha to watch for in production code.

Summary

.service() constructs an instance via new; .factory() returns an explicit value; DI matches by parameter name, which requires explicit annotation to survive minification.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.

Next: The Digest Cycle