# Injection scopes
The scope of a Provider defines the lifecycle and visibility of that bean in the context in which it is used.
Ts.ED DI defines 3 types of
Scope
: singleton
, request
and instance
which can be used on Provider
, Service
, Middleware
and Controller
.
# Singleton scope
Singleton scope is the default behavior of all providers. That means all providers are created during server initialization.
import {Get} from "@tsed/schema";
import {Controller, ProviderScope, Scope} from "@tsed/di";
@Controller("/")
@Scope(ProviderScope.SINGLETON) // OPTIONAL, leaving this annotation a the same behavior
export class MyController {
private rand = Math.random() * 100;
@Get("/random")
async getValue() {
return this.rand;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
Note
In this example all requests on /random
endpoint return the same random value.
# Request scope
Request scope will create a new instance of provider for each incoming request. A new container will be created
and attached to the request. It will contain all providers annotated by @Scope(ProviderScope.REQUEST)
.
import {Get} from "@tsed/schema";
import {Controller, ProviderScope, Scope} from "@tsed/di";
@Controller("/")
@Scope(ProviderScope.REQUEST)
export class MyController {
private rand = Math.random() * 100;
@Get("/random")
async getValue() {
return this.rand;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
Each request on /random
will return a different random value.
# Chain with Service
It is also possible to use @Scope(ProviderScope.REQUEST)
on a service if your service is injected on a controller
which is annotated by @Scope(ProviderScope.REQUEST)
too.
Here is a working example:
import {Get} from "@tsed/schema";
import {Controller, Injectable, ProviderScope, Scope} from "@tsed/di";
@Injectable()
@Scope(ProviderScope.REQUEST)
export class MyService {
public rand = Math.random() * 100;
}
@Controller("/")
@Scope(ProviderScope.REQUEST)
export class MyController {
constructor(private myService: MyService) {}
@Get("/random")
async getValue() {
return this.myService.rand;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
And here is an unworking example:
import {Get} from "@tsed/schema";
import {Controller, Injectable, ProviderScope, Scope} from "@tsed/di";
@Injectable()
@Scope(ProviderScope.REQUEST)
export class MyService {
public rand = Math.random() * 100;
}
@Controller("/")
@Scope(ProviderScope.SINGLETON) // SINGLETON avoid all Scope("request") annotation
export class MyController {
constructor(private myService: MyService) {}
@Get("/random")
async getValue() {
return this.myService.rand;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
WARNING
The SINGLETON
annotation avoids the @Scope(ProviderScope.REQUEST)
annotation put on MyService.
WARNING
The @Scope(ProviderScope.REQUEST)
annotation has no effect on Global middlewares.
# Performance
Using request-scoped providers will obviously affect application performance. Even though Ts.ED is trying to cache as much metadata as possible, it will still have to create an instance of your class on each request. Hence, it will slow down your average response time and overall benchmarking result. If your provider doesn't necessarily need to be request-scoped, you should rather stick with the singleton scope.
# Instance scope
Instance scope used on a provider tells the injector to create a new instance each time the provider is injected to another one.
import {Get} from "@tsed/schema";
import {Controller, Injectable, ProviderScope, Scope} from "@tsed/di";
@Injectable()
@Scope(ProviderScope.INSTANCE)
export class MyInstanceService {
private rand = Math.random() * 100;
@Get("/random")
async getValue() {
return this.rand;
}
}
@Controller("/")
@Scope(ProviderScope.SINGLETON)
export class MyController {
constructor(instance1: MyInstanceService, instance2: MyInstanceService) {
console.log("IsSame", instance1 === instance2);
console.log("instance1", instance1.getValue());
console.log("instance2", instance2.getValue());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Last Updated: 3/7/2021, 9:33:39 PM
Other topics
- Session & cookies
- Passport.js
- Keycloak
- Prisma
- TypeORM
- MikroORM
- Mongoose
- GraphQL
- Socket.io
- Swagger
- AJV
- Multer
- Serve static files
- Templating
- Serverless HTTP
- Seq
- OIDC
- Stripe
- Agenda
- Terminus
- Serverless
- IORedis
- Controllers
- Providers
- Model
- JsonMapper
- Middlewares
- Pipes
- Interceptors
- Authentication
- Hooks
- Exceptions
- Throw HTTP Exceptions
- Cache
- Command
- Response Filter
- Injection scopes
- Custom providers
- Lazy-loading provider
- Custom endpoint decorator
- Testing
- Customize 404