简体   繁体   English

异步打字稿/ JavaScript和依赖注入

[英]Asynchronous Typescript/JavaScript and Dependency Injection

I am fairly new to Typescript/JavaScript. 我对Typescript / JavaScript很陌生。 So this probably a noob question: 所以这可能是一个菜鸟问题:

I have a Typescript class, lets call it serviceActions . 我有一个Typescript类,可以称之为serviceActions

In the constructor of that class I make a connection to a Web API service via BreezeJS. 在该类的constructor中,我通过BreezeJS连接到Web API服务。 I also get the metadata for service ( fetchMetadata ). 我还获得了服务的元数据( fetchMetadata )。

However, the fetchMetadata call returns a promise. 但是, fetchMetadata调用返回一个fetchMetadata So the constructor returns before it is done. 因此, constructor将在完成之前返回。

Now this serviceActions class is injected (via Aurelia) into another class: 现在,这个serviceActions类被注入(通过Aurelia)到另一个类中:

@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. 因此,当调用createNewBox时, fetchMetadata调用未完成,并且调用出错。

Now I could put in an initialize method on my ServiceActions class. 现在,我可以在ServiceActions类上放置一个initialize方法。 But then I have to wrap everything I do in my BoxVM in the promise for that. 但是然后我必须将我所做的一切都包装在BoxVM中,以实现这一目标。 All calls to get data, save data create any entity would have to be done in a call to initalize.then . 所有获取数据,保存数据的调用都将创建任何实体,都必须在initalize.then调用中完成。

Is there another way? 还有另一种方法吗? Am I missing the point? 我错过了重点吗? Or is this the way that Typescript/JavaScript is done? 还是用Typescript / JavaScript完成的方式?

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. 注射器可让您注入“惰性”依赖项,您必须先调用.get().then(callback)才能使用该依赖项。

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. 但总的来说,是的:每当您需要使用异步操作生成的内容时,就需要通过promise接口访问它。 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. 一旦TypeScript添加了更好的async/await支持,这在语法上将变得更加容易,但是如果该资源是通过异步操作生成的,则不能仅仅假设您可以访问该资源以进行注入。

The problem is that ServiceActions is waiting for a promise to be fulfilled before it can be usable. 问题在于ServiceActions在等待兑现可用之前正在等待兑现承诺。 There are several solutions: 有几种解决方案:

  1. Wait for ES7, which lets us await the results of a promise. 等待ES7,这让我们await承诺的结果。 Your createNewBox function will wait patiently for the promise to finish before returning. 您的createNewBox函数将耐心等待诺言完成,然后再返回。 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). 找出将fetchMetadata的结果fetchMetadata到构造函数中的方法(可能在运行DI框架初始化之前进行调用)。 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). 使用initialize().then执行您建议的操作,尽管它似乎容易出错(某些人可能会忘记将代码包装在init中)。
  4. Create an onInit function in ServiceActions that takes a callback - it's a mildly refactored version of what you're suggesting. ServiceActions中创建一个onInit函数-它是您所建议内容的轻度重构版本。
  5. Have createNewBox return a promise to hand over a new Box once ServiceActions is done waiting for the fetchMetadata promise. 一旦ServiceActions完成等待fetchMetadata承诺, fetchMetadata createNewBox返回一个承诺以移交新Box This might pollute everything with many promises. 这可能会污染许多承诺的一切。

I would try for option 2, especially since you seem to need to call this only once. 我会尝试选项2,尤其是因为您似乎只需要调用一次即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM