如何在基于服务的 Angular2 项目中使用依赖注入

How to use dependency injection in service based Angular2 project

问题

在过去的一周里,我一直在为 Angular2 项目开发一个身份验证库。这个库主要是基于服务的,应该几乎可以直接开箱即用。您唯一需要做的就是将它包含在您的应用程序中并为其设置配置对象。

这里的主要服务是AuthService。此服务包括 Http 和另一个自定义服务。问题是,这两个依赖项都需要开发人员指出这些 classes 的提供者。我不确定我是否做对了,但我已经看到他们需要导入 HTTP_PROVIDERS 才能使用 Http 的解决方案。

因此,如果我将 AuthService 作为依赖项导入,我仍然需要导入 HTTP_PROVIDERS 和自定义服务以使 DI 工作。

bootstrap(App, [AuthService, HTTP_PROVIDERS, CustomService]);

这打乱了我认为该模块易于包含的想法。我只想提供导入 AuthService。

到目前为止我尝试过的东西

首先,我开始阅读一些关于 Angular2 中的 DI 的博客。正如你们中的大多数人可能知道的那样,Thoughtram 在提供这些信息方面做得很好(也 EggHead.io)。我最终阅读了这两篇文章:

http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html http://blog.thoughtram.io/angular/2015/09/17/resolve-service-dependencies-in-angular-2.html

看完之后,我觉得解决办法很简单,但过了一会儿,情况似乎并非如此。我想我在这里错过了重点。也在 Spring 启动,其中 DI 是主要卖点,我没有设法让它工作似乎很奇怪(可能是 Angular2 仍处于 Alpha 阶段并且文档稀缺的事实)。

我尝试过的解决方案

所以我尝试了一些我想出的解决方案,但 none 成功了。

提供常量

我的第一个想法是查看 HTTP_PROVIDERS 常量,它类似于 Http 依赖项的提供程序。我最终查看了它的源代码。

https://github.com/angular/angular/blob/b0009f03d510370d9782cf76197f95bb40d16c6a/modules/angular2/http.ts#L151

在那之后我认为我最好尝试为我自己的 class 实现它。

export const AUTH_PROVIDERS: any[] = [
  provide(AuthService, {
    useFactory: (http, customService) => new AuthService(http, customService),
    deps: [Http, CustomService]
  })
  ,
  provide(CustomService, {
    useFactory: () => new CustomService(),
  })
];

完成后,我将其包含在我的 bootstrap 函数中,之后遇到另一个错误。

Token must be defined!

我花了一些时间试图找到问题所在,但我没有找到。

使用注解

Angular2 中的一个新事物是注解。所以我希望其中之一能够帮助我解决我的问题。 @Component@View 似乎不是我需要的。我相信他们更关注功能性对象的视觉方面(因为 View 不是我需要的东西,而是强制性的)。

下一部分看起来很奇怪,因为我找不到这是否是注释(可能不是……)。我试着给@Provider 一个机会。这导致了以下 "possible" 解决方案。

@Provider({
  token: 'AuthService',
  useFactory: (http, customService) => new AuthService(http, customService)
  ...
})
export class AuthService{
  constructor(http: Http, customService, CustomService){...}
}

这只是给了我另一个错误,但这次是由 Typescript 编译器抛出的。

error TS2348: Value of type 'typeof Provider' is not callable. Did you mean to include 'new'?

无论如何,有人可以帮我解决这个问题。上述解决方案之一是朝着正确方向迈出的一步,还是我做错了什么?

提前致谢。

嗯,我发现了问题,但这是我以前没有想到的(可能是因为我主要使用 Java 工作)。 Typescript(最终 JavaScript)不喜欢的一件事是引用在您需要的代码段下方定义的 Class。我想这就是 'Token must be defined!' 错误的来源。无论如何切换代码片段解决了问题。

export class AuthService{...implementation...}

export const AUTH_PROVIDERS : any[] = [
  HTTP_PROVIDERS,
  provide(AuthService, {
    useFactory: (http, customService) => new AuthService(http, customService),
    deps: [Http, CustomService]
  }),
  provide(CustomService, {
    useFactory: () => new CustomService()
  })
];

希望这对以后的其他人有所帮助。