🔒
Services & DI

Singleton Pattern in Angular

Ek Hi Instance, Sabke Liye
💡 Singleton service ek company ka SHARED database jaisa hai — sab departments (components) SAME database access karte hain, har department apna alag database nahi banata — consistency guarantee hoti hai.

providedIn: 'root' wala service ek TRUE SINGLETON hai — poore application mein SIRF EK instance banता hai, chahe kितne bhi components use karein. Ye state SHARING ke liye perfect hai — jaise ek shopping cart service jiski state sab components mein consistent honi chahiye.

@Injectable({ providedIn: 'root' })
export class CartService {
  private items: any[] = [];

  addItem(item: any) {
    this.items.push(item);
  }

  getItemCount() {
    return this.items.length;
  }
}

// Component A mein add karo:
// this.cartService.addItem(product);

// Component B mein (COMPLETELY different part of app) count dekho:
// this.cartService.getItemCount();   — SAME data, kyunki singleton hai!
🔒
Singleton service ek company ka SHARED database jaisa hai — sab departments (components) SAME database access karte hain, har department apna alag database nahi banata — consistency guarantee hoti hai.
1 / 6
⚡ झट से Recap
  • providedIn: 'root' = true singleton, poore app mein ek instance
  • State sharing/consistency ke liye perfect (jaise shopping cart)
  • Simple state management approach — bade apps NgRx/Signals bhi use karte hain
इस page में (2 subtopics)

Agar EK service ko root-level (providedIn: 'root') AUR component-level (providers: [...]) DONO jagah declare kar do, component-level WINS — accidentally do alag instances ban jaate hain, jo confusing bugs deta hai.

@Injectable({ providedIn: 'root' })
export class CounterService {
  count = 0;
}

@Component({
  selector: 'app-child',
  providers: [CounterService]   // OOPS — naya, ALAG instance banega yaha
})
export class ChildComponent { }
// ChildComponent ka CounterService, root-level singleton se DIFFERENT hai!
⚠️Common Mistake: Ye ek subtle, common bug hai — agar service ko GENUINELY singleton hona chahiye (state share karna hai), USE component providers[] mein DUBARA list mat karo, sirf root-level @Injectable configuration par bharosa karo.

Singleton services ka state TESTS ke beech "leak" ho sakta hai (agar properly reset na kiya jaaye) — Angular testing utilities (TestBed) har test ke liye FRESH injector create karte hain, is problem ko avoid karne ke liye.

// Test file mein:
beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [CartService]
  });
  // Har test ko apna FRESH CartService instance milta hai
});
💡Tip: TestBed Angular ka testing utility hai jo automatically dependency injection ko test-friendly banata hai — real singleton behavior production mein hai, lekin tests isolated rehte hain, ek doosre ke state se affect nahi hote.