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
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
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.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.