Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous Typescript/JavaScript and Dependency Injection

I am fairly new to Typescript/JavaScript. So this probably a noob question:

I have a Typescript class, lets call it serviceActions.

In the constructor of that class I make a connection to a Web API service via BreezeJS. I also get the metadata for service (fetchMetadata).

However, the fetchMetadata call returns a promise. So the constructor returns before it is done.

Now this serviceActions class is injected (via Aurelia) into another class:

@autoinject
export class BoxVm {
    constructor(serviceActions: serviceActions) { 
        this.box = this.serviceActions.createNewBox();
    }

So I never really get to await anything. So when the createNewBox is called, the fetchMetadata call is not done, and the call errors out.

Now I could put in an initialize method on my ServiceActionsclass. But then I have to wrap everything I do in my BoxVM in the promise for that. All calls to get data, save data create any entity would have to be done in a call to initalize.then.

Is there another way? Am I missing the point? Or is this the way that Typescript/JavaScript is done?

like image 575
Vaccano Avatar asked Jun 07 '26 09:06

Vaccano


2 Answers

The problem is that ServiceActions is waiting for a promise to be fulfilled before it can be usable. There are several solutions:

  1. Wait for ES7, which lets us await the results of a promise. Your createNewBox function will wait patiently for the promise to finish before returning. This is the cleanest solution.
  2. Figure out a way to pass the results of fetchMetadata into the constructor (possibly making the call before running your DI framework initialization). This avoids the problem.
  3. Do what you suggest with initialize().then, though it seems mildly error-prone (someone might forget to wrap code in init).
  4. Create an onInit function in ServiceActions that takes a callback - it's a mildly refactored version of what you're suggesting.
  5. Have createNewBox return a promise to hand over a new Box once ServiceActions is done waiting for the fetchMetadata promise. This might pollute everything with many promises.

I would try for option 2, especially since you seem to need to call this only once.

like image 164
mk. Avatar answered Jun 10 '26 12:06

mk.


I think this is more a question of how your framework works with dependency injection. Syringe lets you inject a "lazy" dependency, which you have to call .get().then(callback) on in order to use that dependency.

In general, though, yes: any time you need to use something that gets produced by an asynchronous operation, you're going to need to access it through the promise interface. This will become syntactically easier once TypeScript adds better async/await support, but you can't just assume you've got access to a resource for injection if that resource is produced via an asynchronous operation.

like image 29
StriplingWarrior Avatar answered Jun 10 '26 11:06

StriplingWarrior



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!