Appearance
Scoped Service - Scope-Based Instance
Scoped services that share the same instance within a specific scope.
🎯 What is it?
Scoped scope ensures that the service has a single instance within a specific scope. Different instances are created in different scopes.
📦 Usage
typescript
import { xscoped } from '@xcons/widget';
@xscoped()
export class RequestService {
private requestId = Date.now();
getRequestId() {
return this.requestId;
}
}💡 When to Use?
- Request Context: Separate context for each request
- Session Management: Session-based data
- Transaction: Transaction-based scope
- User Context: User-based context
- Temporary State: Temporary state management
📋 Examples
Request Context
typescript
@xscoped()
export class RequestContext {
private context = {
requestId: Date.now(),
userId: null,
timestamp: new Date()
};
setUserId(userId: string) {
this.context.userId = userId;
}
getContext() {
return this.context;
}
}Transaction Service
typescript
@xscoped()
export class TransactionService {
private transactionId = `tx-${Date.now()}`;
private operations: string[] = [];
addOperation(op: string) {
this.operations.push(op);
}
commit() {
console.log(`Committing ${this.transactionId}:`, this.operations);
this.operations = [];
}
rollback() {
console.log(`Rolling back ${this.transactionId}`);
this.operations = [];
}
}User Session
typescript
@xscoped()
export class UserSession {
private sessionData = {
userId: null,
permissions: [],
loginTime: Date.now()
};
setUser(userId: string, permissions: string[]) {
this.sessionData.userId = userId;
this.sessionData.permissions = permissions;
}
hasPermission(permission: string) {
return this.sessionData.permissions.includes(permission);
}
getSessionDuration() {
return Date.now() - this.sessionData.loginTime;
}
}Scoped Cache
typescript
@xscoped()
export class ScopedCache {
private cache = new Map<string, any>();
private scopeId = Math.random();
set(key: string, value: any) {
this.cache.set(key, value);
}
get(key: string) {
return this.cache.get(key);
}
getScopeId() {
return this.scopeId;
}
clear() {
this.cache.clear();
}
}🔧 Scope Management
Scope Cleanup
typescript
import { ServiceRegistry } from '@xcons/widget';
const registry = ServiceRegistry.getInstance();
// Clear scoped services
registry.clearScope('scoped');
// onServiceDestroy is called automaticallyUsage with Lifecycle
typescript
@xscoped()
export class ScopedResource implements OnServiceInit, OnServiceDestroy {
private resourceId = `resource-${Date.now()}`;
onServiceInit() {
console.log(`${this.resourceId} initialized`);
}
onServiceDestroy() {
console.log(`${this.resourceId} cleaning up`);
}
}📊 Behavior
typescript
@xscoped()
class MyService {
value = Math.random();
}
// Same instance within the same scope
const service1 = injector.inject(MyService);
const service2 = injector.inject(MyService);
console.log(service1 === service2); // true
// Clear scope
registry.clearScope('scoped');
// New instance in new scope
const service3 = injector.inject(MyService);
console.log(service1 === service3); // false🔄 Usage Scenario
HTTP Request Pipeline
typescript
// New scope for each request
@xscoped()
export class RequestPipeline {
private steps: string[] = [];
addStep(step: string) {
this.steps.push(step);
}
async execute() {
for (const step of this.steps) {
console.log(`Executing: ${step}`);
await this.executeStep(step);
}
}
private async executeStep(step: string) {
// Step execution logic
}
}
// Usage in middleware
app.use((req, res, next) => {
// New scope at request start
const pipeline = injector.inject(RequestPipeline);
pipeline.addStep('auth');
pipeline.addStep('validate');
// Clear scope at request end
res.on('finish', () => {
registry.clearScope('scoped');
});
next();
});⚠️ Points to Consider
- Scope must be manually cleared
- Same instance within each scope
- onServiceDestroy is called when scope is cleared
- Requires more control than Singleton and Transient
✨ Summary
- ✅ Same instance scope-based
- ✅ Manual scope management
- ✅ Ideal for Request/Session context
- ✅ Isolated state managemen