1

I am having trouble implementing singleton, because class marked as @singleton() is being recreated on every resolve().

Here is the example

// Foo.ts This is singleton and and must be created only once
import { injectable, singleton } from "tsyringe";

@injectable()
@singleton()
export class Foo {
  constructor() {
    console.log("Constractor of Foo");
  }
}
// Bar.ts this is Bar and should be created every time. It uses the singleton
import { inject, injectable, Lifecycle, scoped } from "tsyringe";
import { Foo } from "./Foo";

@injectable()
export class Bar {
  constructor(@inject("Foo") private foo: Foo) {
    console.log("Constractor of Bar");
  }
}
// main.ts this is resolving Bar two times.
// expected output:
// Constractor of Foo
// Constractor of Bar
// Constractor of Bar

// Actual output:
// Constractor of Foo
// Constractor of Bar
// Constractor of Foo
// Constractor of Bar

import "reflect-metadata";
import { container } from "tsyringe";
import { Bar } from "./Bar";
import { Foo } from "./Foo";

container.register("Foo", { useClass: Foo });
container.register("Bar", { useClass: Bar });

const instance = container.resolve(Bar);
const instance1 = container.resolve(Bar);

How can I get the desired behavior?

CyberProdigy
  • 737
  • 9
  • 20

2 Answers2

3

Singleton should be registered as follows

container.register(
  "Foo",
  { useClass: Foo },
  { lifecycle: Lifecycle.Singleton } // <- this is important
);
CyberProdigy
  • 737
  • 9
  • 20
3

I think you are making your life more difficult. I see a couple of things wrong with what you did and the solution you proposed. Here's the source code for the @singleton() decorator:

function singleton<T>(): (target: constructor<T>) => void {
  return function(target: constructor<T>): void {
    injectable()(target);
    globalContainer.registerSingleton(target);
  };
}
  • First of all, you don't need to decorate with @injectable() because tsyringe already adds it with @singleton().
  • Finally, if you just don't register Foo and Bar they will automatically be registered as singleton (with the { lifecycle: Lifecycle.Singleton } option already set, of course) in the globalContainer.registerSingleton(target) function.
Bernat Felip
  • 323
  • 5
  • 18