Skip to content
Zach Collins edited this page Jul 14, 2015 · 3 revisions

After you've run the code generator on your modules, you can use them to create an object graph containing singletons of the services and config built by your providers.

Instantiating the Object Graph

There are two methods for creating an object graph, pitcher.forEntry and pitcher.build. Under the hood, they perform the exact same work, except that forEntry chains into a .build method that accepts the remaining arguments of pitcher.build. The main reason for this is simply to give typescript better type interference on the graph being constructed. Because of the way typescript infers the types of parameters, this division of arguments across two calls is useful, although more explicit.

import { AppModule } from "generated-modules/app";

var objectGraph = pitcher.forEntry(new AppModule()).build();

The above is equivalent in every way to

import { AppModule } from "generated-modules/app";

var objectGraph = pitcher.build(new AppModule());

Providing Override Modules

There are many cases where you may wish to override the definition of a provider in an object graph, say, to stub out a service for testing. You can achieve this by providing explicit module instances to the forEntry(A).build(...) or .build(A, ...). The providers defined by those given explicit module instances will override any providers by the same name in the original module A.

import { AppModule } from "generated-modules/app";
import { FakeDbModule } from "generated-modules/fake-db";

var objectGraph = pitcher.forEntry(new AppModule()).build(new FakeDbModule());

Accessing objects on the Object Graph

pitcher will generated a typed object representing every provider your object graph has defined. For a provider named server, the property name will be serverProvider.

You can then access the underlying value by invoking get.

var [server, err, _] = objectGraph.serverProvider.get();

Note that all providers are lazy, and thus the singleton services will only be created once they are needed as a dependency, or are retrieved from the graph.

Any errors that occur while attempting to get a provider's value will be surfaced as err, and will not throw an exception by default.

Retrieving asynchronous providers

The provider method .get() also accepts a callback to be invoked when the provider is ready. This can be used synchronously, but is most useful when the underlying value might be asynchronous.

objectGraph.serverProvider.get((server, err) => {
  // check for err, then do something with server
});

Why not promises?

It might ponder one why the provider interface does not return a promise itself. Although the reader use a library to provide this convenience, there's a couple of reasons why it is not included by default.

  1. pitcher will invoke the callback immediately if the underlying value is synchronous. Promises cannot do this by spec.
  2. pitcher itself supports Providers of Promises. Since a Promise would chain with itself, we could not have .get() return a Promise<Promise>.