Skip to content

Commit 76d0a29

Browse files
feat(ContainerInstance): disable eager services by default
Eager services are harder to test, and make application behaviour more brittle. As a result, I do personally discourage using them. Therefore, by default they are now disabled. This will need more testing. Some further remarks below: Eager loading is generally discouraged, as it makes testing harder and makes the application more confusing to work with. For instance, see: [typestack/typedi#380](typestack/typedi#380). Consider an example of a DatabaseService with eager loading enabled. Once imported, database connections and more will immediately start taking place. In many cases, this will be unexpected and will ultimately be an unwanted side effect. Therefore, we place the eager loading functionality behind a toggleable option, which must be enabled prior to any eager loading strategies taking place. feat(ContainerInstance): disable eager services by default Eager services are harder to test, and make application behaviour more brittle. As a result, I do personally discourage using them. Therefore, by default they are now disabled. This will need more testing. Some further remarks below: Eager loading is generally discouraged, as it makes testing harder and makes the application more confusing to work with. For instance, see: [typestack/typedi#380](typestack/typedi#380). Consider an example of a DatabaseService with eager loading enabled. Once imported, database connections and more will immediately start taking place. In many cases, this will be unexpected and will ultimately be an unwanted side effect. Therefore, we place the eager loading functionality behind a toggleable option, which must be enabled prior to any eager loading strategies taking place. feat(ContainerInstance): disable eager services by default Eager services are harder to test, and make application behaviour more brittle. As a result, I do personally discourage using them. Therefore, by default they are now disabled. This will need more testing. Some further remarks below: Eager loading is generally discouraged, as it makes testing harder and makes the application more confusing to work with. For instance, see: [typestack/typedi#380](typestack/typedi#380). Consider an example of a DatabaseService with eager loading enabled. Once imported, database connections and more will immediately start taking place. In many cases, this will be unexpected and will ultimately be an unwanted side effect. Therefore, we place the eager loading functionality behind a toggleable option, which must be enabled prior to any eager loading strategies taking place.
1 parent 2f63f59 commit 76d0a29

File tree

1 file changed

+51
-2
lines changed

1 file changed

+51
-2
lines changed

src/container-instance.class.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export const enum ServiceIdentifierLocation {
4646
None = 'none',
4747
}
4848

49+
export const enum EagerLoadingStrategy {
50+
Enabled,
51+
Disabled
52+
}
53+
4954
interface ManyServicesMetadata {
5055
tokens: Token<unknown>[];
5156
scope: ContainerScope;
@@ -82,6 +87,18 @@ export class ContainerInstance implements Disposable {
8287
*/
8388
public static readonly defaultContainer = new ContainerInstance('default');
8489

90+
/**
91+
* The eager loading strategy for use for this container.
92+
*
93+
* If this is set to `Enabled`, then eager loading will take place.
94+
* However, if this is `Disabled`, it shall not.
95+
*
96+
* @remarks
97+
* It should generally be noted that, before any eager services are
98+
* imported, this should be set to enabled to ensure expected behaviour.
99+
*/
100+
private eagerLoadingStrategy = EagerLoadingStrategy.Enabled;
101+
85102
/**
86103
* Create a ContainerInstance.
87104
*
@@ -515,7 +532,11 @@ export class ContainerInstance implements Disposable {
515532
* when the service is also marked as transient. In that case we ignore
516533
* the eager flag to prevent creating a service what cannot be disposed later.
517534
*/
518-
if (newMetadata.eager && newMetadata.scope !== 'transient') {
535+
if (
536+
newMetadata.eager &&
537+
newMetadata.scope !== 'transient' &&
538+
this.eagerLoadingStrategy === EagerLoadingStrategy.Enabled
539+
) {
519540
this.get(newMetadata.id);
520541
}
521542

@@ -631,7 +652,9 @@ export class ContainerInstance implements Disposable {
631652
* @throws Error
632653
* This exception is thrown if the container has been disposed.
633654
*/
634-
public reset(options: { strategy: 'resetValue' | 'resetServices' } = { strategy: 'resetValue' }): this {
655+
public reset(
656+
options: { strategy: 'resetValue' | 'resetServices' | 'clearServices' } = { strategy: 'resetValue' }
657+
): this {
635658
this[THROW_IF_DISPOSED]();
636659

637660
switch (options.strategy) {
@@ -643,6 +666,9 @@ export class ContainerInstance implements Disposable {
643666
this.metadataMap.clear();
644667
this.multiServiceIds.clear();
645668
break;
669+
case 'clearServices':
670+
this.metadataMap.clear();
671+
this.multiServiceIds.clear();
646672
default:
647673
throw new Error('Received invalid reset strategy.');
648674
}
@@ -912,6 +938,29 @@ export class ContainerInstance implements Disposable {
912938
}
913939
}
914940

941+
/**
942+
* Enable eager loading of services for this container.
943+
* @experimental
944+
* <br />
945+
*
946+
* __Note: Ensure this is set before importing any eager services.__
947+
*
948+
* @remarks
949+
* Eager loading is generally discouraged, as it makes testing harder
950+
* and makes the application more confusing to work with.
951+
* For instance, see [typestack/typedi#380](https://github.com/typestack/typedi/issues/380).
952+
*
953+
* Consider an example of a DatabaseService with eager loading enabled.
954+
* Once imported, database connections and more will immediately start taking place.
955+
* In many cases, this will be unexpected and will ultimately be an unwanted side effect.
956+
*
957+
* Therefore, we place the eager loading functionality behind a toggleable option,
958+
* which must be enabled prior to any eager loading strategies taking place.
959+
*/
960+
public enableEagerLoading () {
961+
this.eagerLoadingStrategy = EagerLoadingStrategy.Enabled;
962+
}
963+
915964
/** Iterate over each service in the container. */
916965
public [Symbol.iterator](): IterableIterator<[ServiceIdentifier, ServiceMetadata<unknown>]> {
917966
return this.metadataMap.entries();

0 commit comments

Comments
 (0)