Dependency Injection

Disposing Services

Cleaning up services with app.dispose and provider.dispose, closing the navigation scope, tracking transient instances.

Disposing services

The provider disposes the instances it built itself. If a service holds a resource such as a timer, a listener or a connection, write a dispose() method that releases it; calling it is the provider's job:

@Injectable({ lifetime: "singleton" })
export class SyncService {
  private timer = setInterval(() => this.pull(), 60_000);

  async pull() {
    const response = await fetch("/api/notes");
    return response.json();
  }

  dispose() {
    clearInterval(this.timer);
  }
}
@Injectable({ lifetime: "singleton" })
export class SyncService {
  timer = setInterval(() => this.pull(), 60_000);

  async pull() {
    const response = await fetch("/api/notes");
    return response.json();
  }

  dispose() {
    clearInterval(this.timer);
  }
}

When they are disposed:

How: on every instance, dispose(), close(), [Symbol.dispose]() and [Symbol.asyncDispose]() are called in order if they exist; an error thrown by one does not stop the others.

Only instances that have been built are disposed: a singleton that was never asked for was never built, so it is not disposed either; a value given with useValue goes through this only if it has been resolved at least once.

transient instances are not tracked by default; when provider.enableAutoDisposeTransients() is turned on, transient instances produced in a child scope (createScope, a navigation scope) are disposed together with that scope. Transients resolved from the root provider are still not tracked.

provider.getAllServices() gives the ServiceCollection the provider uses.

Next step

For the mechanisms that writing packages on MotifJS relies on, go on to Writing Packages on Motif.