InversifyJS icon indicating copy to clipboard operation
InversifyJS copied to clipboard

toService not working for async services

Open AGrzes opened this issue 4 years ago • 0 comments

Expected Behavior

At the moment it is possible to define service having asynchronous @postConstruct() method making it asynchronous and it would be great to have it work together with toService binding.

Current Behavior

As toService is doing basically

    BindingToSyntax.prototype.toService = function (service) {
        this.toDynamicValue(function (context) { return context.container.get(service); });
    };

It breaks as getAsync need to be used.

Possible Solution

Add new api method

    BindingToSyntax.prototype.toAsyncService = function (service) {
        this.toDynamicValue(function (context) { return context.container.getAsync(service); });
    };

Steps to Reproduce (for bugs)

import { Container, injectable, multiInject, postConstruct } from 'inversify'
import 'reflect-metadata'

@injectable()
class A {
  constructor(@multiInject('X') x) {
    console.log(x)
  }
}

@injectable()
class B {
  @postConstruct()
  async init() {}
}

const container = new Container()
container.bind(B).toSelf().inSingletonScope()
container.bind(A).toSelf()
container.bind('X').toService(B)
container.getAsync(A).then(console.log).catch(console.error)

npx ts-node test.ts

Error: You are attempting to construct 'class B {
    async init() { }
}' in a synchronous way
 but it has asynchronous dependencies.
    at Container._getButThrowIfAsync (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/container/container.ts:583:13)
    at Container.get (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/container/container.ts:325:17)
    at Binding.dynamicValue (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/syntax/binding_to_syntax.ts:96:38)
    at /home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/resolution/resolver.ts:51:86
    at tryAndThrowErrorIfStackOverflow (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/utils/exceptions.ts:12:12)
    at _resolveFactoryFromBinding (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/resolution/resolver.ts:50:41)
    at _getResolvedFromBinding (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/resolution/resolver.ts:85:16)
    at /home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/resolution/resolver.ts:111:18
    at _resolveInScope (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/resolution/resolver.ts:100:12)
    at _resolveBinding (/home/abramczykg/git/tuatara-finance-platform/tfp-local-development/modules/cli/node_modules/.pnpm/[email protected]/node_modules/inversify/src/resolution/resolver.ts:110:10)

Context

toService binding is useful to bind the same instance in multiple contexts - for example binding a service both to its own class for direct access and to some token for multi-inject.

Your Environment

  • Version used: 6.0.1

AGrzes avatar Dec 17 '21 11:12 AGrzes