microsoft / tsyringe

Lightweight dependency injection container for JavaScript/TypeScript
MIT License
5.16k stars 173 forks source link

container.hasInstances() or some other way to tell if instances exist without creating new ones #127

Closed mikl closed 2 years ago

mikl commented 4 years ago

I’ve been struggling to find a way to gracefully shut down my Node.js application after adopting TSyringe, since there appears to be no way to get existing instances without creating a new one.

Description

For example, I have a database client defined as

@singleton()
export class CassandraClient {
  // Implementation irrelevant
}

and a shutdown function (using the global container) looking like this:

  if (container.isRegistered(CassandraClient)) {
    for (const client of container.resolveAll(CassandraClient)) {
       client.shutdown())
    }
  }

…if no instances of the (singleton) CassandraClient exists, TSyringe instantiates a new one. Since I’m trying to shut down, that is counter-productive, and leads to problems trying to shut something down that hasn’t really started yet.

Solutions

I don’t really have a preference here, but I imagine one of these could solve the problem:

  1. A container.hasInstances() check that only returns true if a token has been instantiated, not just registered.
  2. A variant of (or parameter to) container.resolveAll() that only returns existing instances, instead of creating new ones.
Xapphire13 commented 4 years ago

Could this be solved by checking to see if the client has been started before calling .shutdown()?

mikl commented 4 years ago

@Xapphire13 just instantiating the class starts it. I even tried subclassing the container to try to get at the existing instances without creating new ones, but since everything has private visibility, that’s not an option either :(

Another option would be to make some of the internal methods protected instead, so it would be possible to customise the container.

Xapphire13 commented 4 years ago

@mikl, would you problem be solved by adding a .dispose() method to the container? This method would dispose all instances that implement:

interface Disposable {
  dispose(): void;
}

and render the container unusable

mikl commented 4 years ago

@Xapphire13 yes, that would be a great solution, imho.