user4092086 user4092086 - 1 year ago 104
TypeScript Question

How to inject an asynchronous dependency in inversify?

I have TypeScript application and I'm using Inversify for IoC.

I have a connection class:

'use strict';
import { injectable } from 'inversify';
import { createConnection, Connection } from "typeorm";
import { Photo, PhotoMetadata, Author, Album } from '../index';

class DBConnectionManager {

public createPGConnection(): Promise<Connection> {
return createConnection({
driver: {
type: "postgres",
host: "host",
port: 5432,
username: "username",
password: "password",
database: "username"
entities: [
Photo, PhotoMetadata, Author, Album
autoSchemaSync: true,



export { DBConnectionManager };

After I created my connection I want to bind a connection into my container:


and then I want to inject it into another class:

import { injectable, inject } from 'inversify';
import { Connection, FindOptions } from "typeorm";
import { IGenericRepository, ObjectType } from '../index';

class GenericRepository<T> implements IGenericRepository<T> {

private connection: Connection;
private type: ObjectType<T>;

constructor( @inject('DefaultConnection') connection: Connection) {
this.connection = connection;

So in my container configuration how can I bind DefaultConnection that needs to wait for CreateConnection
I can do with async and wait but I'm wonder if there is a cleaner way to achive this in inversify

Answer Source

Inversify 2.0 includes support for asynchronous factories (AKA Providers)

A provider allows you can to declare a provider as follows:


         .toProvider<DbClient>((context) => {
            return () => {
                return new Promise<DbClient>((resolve, reject) => {

                    // Create instance
                    let dbClient = context.container.get<DbClient>("DbClient");

                    // Open DB connection
                            .then(() => {
                            .catch((e: Error) => {

Then you can inject and consume the provider. The only problem is that it requires two-step initialization: the constructor injection and the async init() method.

class UserRepository { 

    private _db: DbClient;
    private _dbProvider: Provider<DbClient>;

    // STEP 1
    public constructor(
        @inject("Provider<DbClient>") provider: Provider<DbClient>
    ) { 
        this._dbProvider = provider;

    // STEP 2
    private async init() {
        if (this._db) return this._db;
        this._db = await this._dbProvider();
        return Promise.resolve(this._db);

    public async getUser(): Promise<Users[]>{
        let db = await this.init();
        return db.collections.user.get({});

    public async deletetUser(id: number): Promise<boolean>{
        let db = await this.init();
        return db.collections.user.delete({ id: id });


We are working on a new feature to simplify the injection of asynchronous values. This feature will be included in inversify 3.0:

class UserRepository { 

    // STEP 1
    public constructor(
        @inject("Provider<DbClient>") private provider: Provider<DbClient>
    ) {}

    public async getUser(): Promise<Users[]>{
        // STEP 2: (No initialization method is required)
        let db = await this.provider.someFancyNameForProvideValue;
        return db.collections.user.get({});