【问题标题】:Angular 2 - No provider for ServiceAngular 2 - 没有服务提供者
【发布时间】:2017-09-12 12:30:31
【问题描述】:

我一直在尝试解决 Angular 2 的一个奇怪问题,它没有检测到我的提供程序声明,但没有任何效果。我什至无法在 plunkr 中复制它。

我在路由器 3.0 alpha.8 中使用 angular 2 rc 3。

错误信息是:ORIGINAL EXCEPTION: No provider for TestService!

app.routes.ts:

import { provideRouter, RouterConfig } from '@angular/router';

import { HomeComponent } from './app/home/home.component';
import { LogInComponent } from './app/log-in/log-in.component';
import { SignUpComponent } from './app/sign-up/sign-up.component';

export const routes: RouterConfig = [
  { path: '', component: HomeComponent },
  { path: 'log-in', component: LogInComponent },
  { path: 'sign-up', component: SignUpComponent }
];

export const APP_ROUTER_PROVIDERS = [
  provideRouter(routes)
];

main.ts:

import { bootstrap }    from '@angular/platform-browser-dynamic';
import { enableProdMode } from "@angular/core";

import { AppComponent } from './app/app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';

// enableProdMode();

bootstrap(AppComponent, [
  APP_ROUTER_PROVIDERS
])
.catch(error => console.log(error));

app/app.component.ts:

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';

import { TestService } from './shared/test.service';

@Component({
  selector: 'my-app',
  template: `
    <div id="menu">
      <a [routerLink]="['/sign-up']"><button>Sign Up</button></a>
    </div>
    <router-outlet></router-outlet>
  `,
  directives: [ROUTER_DIRECTIVES],
  providers: [TestService]
})
export class AppComponent {

  constructor() { }

}

app/sign-up/sign-up.component.ts:

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';

import { TestService } from '../shared/test.service';

@Component({
  selector: 'sign-up',
  template: `<h1>Sign up!</h1>`,
  directives: [ROUTER_DIRECTIVES]
})
export class SignUpComponent {
  constructor(private testService: TestService) {
    this.testService.test('works?');
  }


}

app/shared/test.service.ts:

import { Injectable } from '@angular/core';

@Injectable()
export class TestService {

  constructor() { }

  test(message: string) {
    console.log(message);
  }

}

所以,我在基础组件 (app.component.ts) 中提供测试服务,因为我希望我的所有组件都访问同一个实例。但是,当我导航到注册时,我得到了 no provider for testservice 错误。如果我在注册组件中提供 TestService,则可以:

import { Component, OnInit } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';

import { TestService } from '../shared/test.service';

@Component({
  selector: 'sign-up',
  template: `<h1>Sign up!</h1>`,
  directives: [ROUTER_DIRECTIVES],
  providers: [TestService]
})
export class SignUpComponent implements OnInit {
  constructor(private testService: TestService) { }

  ngOnInit() { }

}

但是,我需要在整个应用程序中都可以访问同一个实例,那么如何在主组件级别注入它?

我什至尝试使用相同版本的所有内容复制 plunkr 提供的这个应用级服务,但它似乎没有给我同样的错误......

http://plnkr.co/edit/5bpeHs72NrlyUITCAJim?p=preview

【问题讨论】:

  • 它必须与您的项目配置相关。代码很好,这就是它在 Plunker 中运行的原因。
  • 您认为哪些配置可能值得怀疑?如果有帮助,我可以发布我的 systemjs 配置
  • 我对systemjs了解不多,因为我只是在本地使用Dart。我会尝试使用 angular-cli 创建一个新项目并在那里复制代码位,看看你是否得到同样的错误。
  • 您可以发布自己问题的答案。然后您可以接受它(经过 2 天的冷却阶段),这会导致此问题被标记为已回答。

标签: dependency-injection angular


【解决方案1】:

app 级别上注入一些东西是在bootstrap 中完成的:

main.ts:

import { TestService } from '../shared/test.service';

bootstrap(AppComponent, [
  APP_ROUTER_PROVIDERS, TestService
])

【讨论】:

  • 是的,我也试过了,但它也不起作用。此外:“引导提供程序选项旨在配置和覆盖 Angular 自己的预注册服务,例如其路由支持。首选方法是在应用程序组件中注册应用程序提供程序。”
  • angular.io/docs/ts/latest/api/platform-browser-dynamic/index/…。检查Class export。它说customProviders。它允许任何东西@Injectable
  • 尝试将providers: [TestService] 添加到SignUpComponent
  • 是的,可以在引导程序中提供,但不是首选。但这并不重要,因为它仍然不起作用。此外,在注册组件中添加提供程序是可行的,但是我不能在我的其他组件中使用相同的引用。
  • 根据 Angular2 样式指南,在根组件提供全局服务是首选方式。由于与APP_INITIALIZER 存在一些依赖关系,因此需要为新路由器提供引导程序,否则bootstrap() 和根组件几乎是等效的。
【解决方案2】:

对我来说,对“服务”文件夹的一些引用是“服务”。当我将它们全部设为“服务”(小写)时,它起作用了。

例如:

import {ApiService} from "./Services/api.service";

没用,但这有效:

import {ApiService} from "./services/api.service";

【讨论】:

    【解决方案3】:

    致所有未来的读者——这对于 angular 2.0.0 rc-4 是正确的:

    确保遵循以下文件夹结构:

    根: 索引.html 包.json systemjs.config.js tsconfig.json(如果使用 TypeScript) 打字.json 应用程序(文件夹): - main.js(您的应用程序的根脚本) - app.component.js(整个应用程序的根组件)

    这对于分层注入正确界定和识别提供者至关重要。

    此外,这非常重要 - 如果仍然遇到问题并且您正在使用 TypeScript 或任何其他转译语言 - 删除转译器为有问题的对象图中的每个关联类生成的任何工件 -这一点,OP 的回答最终对我有所帮助(*.map.js 和 *.js 文件被删除并重新编译)。

    【讨论】:

    • 哇。在我发现这个之前,我一直在发疯。我不明白为什么我的组件无法识别服务的全局注册。直到我找到了层次结构的东西。谢谢。
    • 嗯。认为它会有所帮助,但仍然...chat.stackoverflow.com/rooms/140220/…
    【解决方案4】:

    毕竟这是一个配置问题,而且完全难以捉摸。

    根据 ang2 风格指南,我的 main.ts 文件夹位于我的主应用程序文件夹中,在 systemjs.config 中,我必须将应用程序的主文件夹声明为 '../main.js'。当我将主文件移动到根应用程序文件夹并将 systemjs 中的包声明更改为 'main.js' 时,它起作用了。

    奇怪的是,在我尝试使用分层依赖注入之前,其他一切都正常工作。

    【讨论】:

      猜你喜欢
      • 2017-08-22
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 2018-07-05
      • 2016-12-20
      • 2015-07-26
      • 2018-01-09
      • 1970-01-01
      相关资源
      最近更新 更多