I'm using inversify
with inversify-express-utils
.
I have a quite usual inversify/express
setup.
- Controller
- Service
- A module
- B module
- A module
- Service
B module
is a class that looks like this:
import { injectable } from 'inversify';
import SpellCorrector from 'spelling-corrector';
@injectable()
export class SpellCorrectorFactory {
private corrector: any;
constructor() {
this.corrector = new SpellCorrector();
this.corrector.loadDictionary();
}
public correct = (text: string): string => this.corrector.correct(text);
}
Now, the problem here is that as you can see in the constructor, I have this line of code:
this.corrector.loadDictionary()
This line takes over a second to execute.
So basically it seems like the actual instance creation is happening when I @inject
service B
to service A
So every time I make a request, the constructor of SpellCorrectorFactory
is being executed, so the request takes over 1000ms instead of below 100ms.
How can I bind this class to inversify so that during binding the class is being instantiated and in the A module
I have access to the instance which was created on app start, and not when I send a request to the express path?
Thanks in advance!
I'm using inversify
with inversify-express-utils
.
I have a quite usual inversify/express
setup.
- Controller
- Service
- A module
- B module
- A module
- Service
B module
is a class that looks like this:
import { injectable } from 'inversify';
import SpellCorrector from 'spelling-corrector';
@injectable()
export class SpellCorrectorFactory {
private corrector: any;
constructor() {
this.corrector = new SpellCorrector();
this.corrector.loadDictionary();
}
public correct = (text: string): string => this.corrector.correct(text);
}
Now, the problem here is that as you can see in the constructor, I have this line of code:
this.corrector.loadDictionary()
This line takes over a second to execute.
So basically it seems like the actual instance creation is happening when I @inject
service B
to service A
So every time I make a request, the constructor of SpellCorrectorFactory
is being executed, so the request takes over 1000ms instead of below 100ms.
How can I bind this class to inversify so that during binding the class is being instantiated and in the A module
I have access to the instance which was created on app start, and not when I send a request to the express path?
Thanks in advance!
Share Improve this question asked Aug 6, 2020 at 22:44 matewilkmatewilk 1,3011 gold badge15 silver badges29 bronze badges 16-
1
I've never used it, but a cursory glance at their documentation indicates support for both singleton registrations and asynchronous factories. The latter is a rare feature in IOC containers. More to the point, why aren't you injecting
SpellCorrector
? As it is, your direct creation of that dependency nullifies the benefits of using such a framework – Aluan Haddad Commented Aug 7, 2020 at 4:06 -
1
When you say "bind", do you mean setter injection? If so it's a bad practice. What I am talking about is constructor injection:
constructor(@inject(SpellCorrector) corrector: SpellCorrector) {}
. It's an interesting framework, but I'm new to it as well. How doesloadDictionary
work? It should return aPromise
. If you are performing synchronous IO, you must stop. JavaScript applications are single-threaded. If it returns aPromise
, you can register an asynchronous provider in inversify. – Aluan Haddad Commented Aug 7, 2020 at 9:10 -
1
Yes, it does make sense. However, since constructors are synchronous, and since you say that takes
loadDictionary
takes 1000+ms, blocking startup. I am asking you howloadDictionary
works. Is it performing synchronous IO? – Aluan Haddad Commented Aug 7, 2020 at 9:31 -
1
It matters a lot. If it is an async IO operation, then your
SpellCorrectorFactory
is in an initially invalid state when it is created, because of how you construct it. – Aluan Haddad Commented Aug 7, 2020 at 9:43 -
1
That it uses
fs.readFileSync
is terrible. JS is single threaded. That means that your application is 100% frozen, unable to do anything else while the file is loading. If it were properly written, it would usefs.promises.readFile
. Then you could register it as a singleton, provided by an async factory, in inversify as documented here, solving all. Seriously though, I cannot overstate how problematic sync IO is in a JS application, client or server, except CLI tools. – Aluan Haddad Commented Aug 7, 2020 at 10:04
1 Answer
Reset to default 5Ok, just in case someone looks at this page in search for an answer.
The solution is as simple as:
container
.bind<SpellCorrectorFactory>(TYPES.SpellCorrector)
.to(SpellCorrectorFactory)
.inSingletonScope();
This calls the constructor of the SpellCorrectorFactory
immediately and returns the instance.
So whenever you inject the result of this binding you have direct access to the instance and its functions.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744300171a4567462.html
评论列表(0条)