【问题标题】:Angular no provider for NameServiceAngular 没有 NameService 的提供者
【发布时间】:2015-08-15 07:13:51
【问题描述】:

我在将类加载到 Angular 组件时遇到问题。我一直在尝试解决它很长时间;我什至尝试将它们全部加入一个文件中。我有的是:

Application.ts

/// <reference path="../typings/angular2/angular2.d.ts" />

import {Component,View,bootstrap,NgFor} from "angular2/angular2";
import {NameService} from "./services/NameService";

@Component({
    selector:'my-app',
    injectables: [NameService]
})
@View({
    template:'<h1>Hi {{name}}</h1>' +
    '<p>Friends</p>' +
    '<ul>' +
    '   <li *ng-for="#name of names">{{name}}</li>' +
    '</ul>',
    directives:[NgFor]
})

class MyAppComponent
{
    name:string;
    names:Array<string>;

    constructor(nameService:NameService)
    {
        this.name = 'Michal';
        this.names = nameService.getNames();
    }
}
bootstrap(MyAppComponent);

services/NameService.ts

export class NameService {
    names: Array<string>;
    constructor() {
        this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
    }
    getNames()
    {
        return this.names;
    }
}

我不断收到一条错误消息,上面写着No provider for NameService

有人可以帮我找出我的代码的问题吗?

【问题讨论】:

  • 从 Alpha 42 开始:@Component({ providers: [NameService] })

标签: typescript angular systemjs


【解决方案1】:

Angular 2 发生了变化,下面是代码顶部的样子:

import {
  ComponentAnnotation as Component,
  ViewAnnotation as View, bootstrap
} from 'angular2/angular2';
import {NameService} from "./services/NameService";

@Component({
  selector: 'app',
  appInjector: [NameService]
})

此外,您可能希望在服务中使用 getter 和 setter:

export class NameService {
    _names: Array<string>;
    constructor() {
        this._names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
    }
    get names() {
        return this._names;
    }
}

然后在您的应用中您可以简单地执行以下操作:

this.names = nameService.names;

我建议你去 plnkr.co 并创建一个新的 Angular 2 (ES6) plunk 并首先让它在那里工作。它会为你准备好一切。一旦它在那里工作,将其复制到您的其他环境并对该环境的任何问题进行分类。

【讨论】:

    【解决方案2】:

    您必须使用providers 而不是injectables

    @Component({
        selector: 'my-app',
        providers: [NameService]
    })
    

    Complete code sample here.

    【讨论】:

    • 未来谷歌员工的更新:使用providers 可在最新的测试版(beta 0)上运行。
    • @nathanhleung 绑定和提供程序都可以工作 - 这是暂时的还是他们只是在内部做同样的事情
    • @Simon_Weaver 嗯,他们可能已经在最新的 beta 版本中更改了它 - 在 beta.0 中我无法让它与 bindings 一起使用
    • @nathanhleung 似乎供应商也进入了发行版。
    • 如果该服务是从另一个服务中使用的怎么办?我将它添加到我认为可以使其在全球范围内可用的模块提供程序中,但仍然出现该错误
    【解决方案3】:

    您还可以在引导命令中声明依赖项,例如:

    bootstrap(MyAppComponent,[NameService]);
    

    至少在 alpha40 中这对我有用。

    这是链接:http://www.syntaxsuccess.com/viewarticle/dependency-injection-in-angular-2.0

    【讨论】:

      【解决方案4】:

      Angular2 要求你在 bootstrap 函数调用中声明所有的可注入对象。没有这个,你的服务就不是一个可注入的对象。

      bootstrap(MyAppComponent,[NameService]);
      

      【讨论】:

      • 这不太正确。我们可以将服务包含在 bootstrap() 或组件配置对象的 providers 数组中。如果它包含在providers 数组中,我们会为每个绑定组件获取一个实例。有关更多信息,请参阅Hierarchical Injectors 文档。
      • 是的,正如@MarkRajcok 所说,我们也只在引导时提供那些我们必须在整个应用程序中使用的服务。通过这样做,我们不需要每次都在提供程序中注入,因为它会为每个组件创建实例。
      【解决方案5】:

      在 Angular 2 中,您可以在三个地方“提供”服务:

      1. 引导
      2. 根组件
      3. 其他组件或指令

      “引导提供程序选项旨在配置和覆盖 Angular 自己的预注册服务,例如它的路由支持。” -- reference

      如果您只希望在整个应用程序中使用一个 NameService 实例(即 Singleton),请将其包含在根组件的 providers 数组中:

      @Component({
         providers: [NameService],
         ...
      )}
      export class AppComponent { ... }
      

      Plunker

      如果您希望每个组件有一个实例,请改用组件配置对象中的providers 数组:

      @Component({
         providers: [NameService],
         ...
      )}
      export class SomeOtherComponentOrDirective { ... }
      

      有关更多信息,请参阅Hierarchical Injectors 文档。

      【讨论】:

      • 这是一个非常好的答案。它进一步解释了在根组件中声明服务与在其他子组件中声明服务之间的区别。
      【解决方案6】:

      从 Angular 2 Beta 开始:

      @Injectable 添加到您的服务中:

      @Injectable()
      export class NameService {
          names: Array<string>;
      
          constructor() {
              this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
          }
      
          getNames() {
              return this.names;
          }
      }
      

      并在您的组件配置中添加 providers 为:

      @Component({
          selector: 'my-app',
          providers: [NameService]
      })
      

      【讨论】:

        【解决方案7】:

        在 Angular v2 及更高版本中:

        @Component({ selector:'my-app', providers: [NameService], template: ... })

        【讨论】:

          【解决方案8】:

          您应该在AppModuleNgModule 元数据的providers 数组中注入NameService

          @NgModule({
             imports: [BrowserModule, ...],
             declarations: [...],
             bootstrap: [AppComponent],
             //inject providers below if you want single instance to be share amongst app
             providers: [MyService]
          })
          export class AppModule {
          
          }
          

          如果您想为特定组件级别创建依赖项而不关心应用程序的状态,那么您可以将该依赖项注入组件 providers 元数据选项,如所示的接受的@Klass 答案。

          【讨论】:

          • 我尝试在 @NgModule 部分的 app.module.shared.ts 中添加服务:提供者:[DataManagerService] 但仍然收到错误:错误:DataManagerService 没有提供者!
          • @Paul 您是否在正确的模块中注入您的服务? DataManagerService 上面有 @Injectable 装饰器吗?
          【解决方案9】:

          您应该在 AppModule 的 NgModule 元数据的 providers 数组中注入 NameService。

          @NgModule({
             providers: [MyService]
          })
          

          并确保以相同的名称(区分大小写)导入您的组件,因为 SystemJs 区分大小写(按设计)。如果您在项目文件中使用不同的路径名,如下所示:

          main.module.ts

          import { MyService } from './MyService';
          

          你的组件.ts

          import { MyService } from './Myservice';
          

          然后系统 js 将进行双重导入

          【讨论】:

          • 太棒了!在使用桶对导入进行分组时,我遇到了这个错误。您的 SystemJS 提示帮助了我 :)
          【解决方案10】:

          您好,您可以在 .ts 文件中使用它:

          首先在这个 .ts 文件中导入你的服务:

          import { Your_Service_Name } from './path_To_Your_Service_Name';
          

          然后你可以在同一个文件中添加providers: [Your_Service_Name]

           @Component({
                selector: 'my-app',
                providers: [Your_Service_Name],
                template: `
                  <h1>Hello World</h1> `   
              })
          

          【讨论】:

            【解决方案11】:

            将其添加到 providers 而不是 injectables

            @Component({
                selector:'my-app',
                providers: [NameService]
            })
            

            【讨论】:

              【解决方案12】:

              No provider for NameService 错误是许多 Angular2 初学者面临的常见问题。

              原因:在使用任何自定义服务之前,您首先必须通过将其添加到提供程序列表来向 NgModule 注册它:

              解决方案:

              @NgModule({
                  imports: [...],
                  providers: [CustomServiceName]
              })
              

              【讨论】:

                【解决方案13】:

                您需要将其添加到 providers 数组中,其中包括您的组件的所有依赖项。

                在 Angular 文档中查看此部分:

                在组件中注册提供者

                这是一个修改后的 HeroesComponent,它在它的 提供者数组。

                import { Component } from '@angular/core';
                
                import { HeroService } from './hero.service';
                
                @Component({
                  selector: 'my-heroes',
                  providers: [HeroService],
                  template: `
                  <h2>Heroes</h2>
                  <hero-list></hero-list>
                  `
                })
                export class HeroesComponent { }
                

                何时使用 NgModule 与应用程序组件

                一方面,NgModule 中的提供者注册在根目录中 注射器。这意味着每个在 NgModule 中注册的提供者 将可在整个应用程序中访问。

                另一方面,在应用程序组件中注册的提供程序 仅在该组件及其所有子组件上可用。

                在这里,APP_CONFIG 服务需要在整个 应用程序,因此它已在 AppModule @NgModule 提供程序中注册 大批。但是由于 HeroService 只在 Heroes 内部使用 功能区和其他任何地方,将其注册在 HeroesComponent。

                另请参阅“我应该将应用范围的提供程序添加到根 AppModule 还是 root AppComponent?”在 NgModule 常见问题解答中。

                因此,在您的情况下,只需将注射剂更改为如下提供者:

                @Component({
                  selector: 'my-app',
                  providers: [NameService]
                })
                

                在新版本的 Angular 中,@View 和其他一些东西也不见了。

                欲了解更多信息,请访问here

                【讨论】:

                  【解决方案14】:

                  将@Injectable 添加到您的服务中:

                  export class NameService {
                      names: Array<string>;
                  
                      constructor() {
                          this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
                      }
                  
                      getNames() {
                          return this.names;
                      }
                  }
                  

                  并在您的组件中将提供者添加为:

                  @Component({
                      selector: 'my-app',
                      providers: [NameService]
                  })
                  

                  或者如果您想在整个应用程序中访问您的服务,您可以传入应用程序提供程序

                  【讨论】:

                    【解决方案15】:

                    将您的服务添加到 app.module.ts 文件中的 providers[] 数组。 如下所示

                    // 这里我的服务是 CarService

                    app.module.ts

                    import {CarsService} from './cars.service';
                    
                    providers: [CarsService] // you can include as many services you have 
                    

                    【讨论】:

                      【解决方案16】:

                      令人震惊的是,最新版本的 Angular 中的语法又发生了变化 :-) 从 Angular 6 docs:

                      从 Angular 6.0 开始,创建单例的首选方式 services 是在服务上指定应该提供的服务 应用程序根。这是通过将providedIn设置为root来完成的 服务的 @Injectable 装饰器:

                      src/app/user.service.0.ts

                      import { Injectable } from '@angular/core';
                      
                      @Injectable({
                        providedIn: 'root',
                      })
                      export class UserService {
                      }
                      

                      【讨论】:

                        【解决方案17】:

                        在 Angular 中,您可以通过两种方式注册服务:

                        1.在模块或根组件中注册服务

                        效果:

                        • 适用于所有组件
                        • 终生适用

                        如果您将服务注册到延迟加载的模块中,您应该小心:

                        • 该服务仅适用于在该模块中声明的组件

                        • 只有在加载模块时,服务才会在生命周期应用程序中可用

                        2。将服务注册到任何其他应用程序组件中

                        效果:

                        • 将服务的单独实例注入到组件中

                        如果您将服务注册到任何其他应用程序组件中,您应该小心

                        • 注入服务的实例将仅可用于组件及其所有子组件。

                        • 实例将在组件生命周期内可用。

                        【讨论】:

                          【解决方案18】:

                          块引用

                          在组件中注册提供者

                          这是一个修改后的 HeroesComponent,它将 HeroService 注册到它的 providers 数组中。

                          import { Component } from '@angular/core';
                          
                          import { HeroService } from './hero.service';
                          
                          @Component({
                            selector: 'my-heroes',
                            providers: [HeroService],
                            template: `
                            `
                          })
                          export class HeroesComponent { }
                          

                          【讨论】:

                            猜你喜欢
                            • 2016-12-20
                            • 1970-01-01
                            • 2019-05-15
                            • 2018-11-17
                            • 2018-08-04
                            • 2018-06-21
                            • 2020-10-10
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多