Angular 7:注入的服务未定义

Posted

技术标签:

【中文标题】Angular 7:注入的服务未定义【英文标题】:Angular 7 : Injected service is undefined 【发布时间】:2019-08-09 08:19:09 【问题描述】:

我试图在 LoginService 中注入 AccountService 但它不会,accountService 未定义但另一方面 authServiceProvider 已定义。

相反,它完美地注入了footerComponent。

那么为什么 AccountService 被完美地注入到 FooterComponent 中并且它在 LoginService 中出现了错误。

我不知道问题出在哪里。

import  Injectable  from '@angular/core';
import  AccountService  from 'app/core/auth/account.service';
import  AuthServerProvider  from 'app/core/auth/auth-jwt.service';
@Injectable( providedIn: 'root' )
export class LoginService 
    constructor(public accountService: AccountService, private authServerProvider: AuthServerProvider) 
        console.log(this.accountService); //  is undefined 
        console.log(this.authServerProvider); // is defined

这是 AuthentificationService

@Injectable( providedIn: 'root' )
export class AuthServerProvider 
    constructor(private http: HttpClient, private $localStorage: LocalStorageService, private $sessionStorage: SessionStorageService) 

这是 AccountService

@Injectable( providedIn: 'root' )
export class AccountService 
    private userIdentity: any;
    private authenticated = false;
    private authenticationState = new Subject<any>();
    constructor(private languageService: JhiLanguageService, private sessionStorage: SessionStorageService, private http: HttpClient) 

我尝试在其他组件中使用 AccountService 并完美注入

import  Component  from '@angular/core';
import  AccountService  from 'app/core';
@Component(
    selector: 'jhi-footer',
    templateUrl: './footer.component.html',
    styleUrls: ['./footer.component.scss']
)
export class FooterComponent 

    constructor( private accountService: AccountService) 
        console.log(this.accountService); // It is defined

    

这是 app.module.ts

import './vendor.ts';
import  NgModule  from '@angular/core';
import  BrowserModule  from '@angular/platform-browser';
import  HTTP_INTERCEPTORS  from '@angular/common/http';
import  NgbDatepickerConfig  from '@ng-bootstrap/ng-bootstrap';
import  Ng2Webstorage  from 'ngx-webstorage';
import  NgJhipsterModule  from 'ng-jhipster';
import  AuthInterceptor  from './blocks/interceptor/auth.interceptor';
import  AuthExpiredInterceptor  from './blocks/interceptor/auth-expired.interceptor';
import  ErrorHandlerInterceptor  from './blocks/interceptor/errorhandler.interceptor';
import  NotificationInterceptor  from './blocks/interceptor/notification.interceptor';
import  SharedModule  from 'app/shared';
import  CoreModule  from 'app/core';
import  AppRoutingModule  from './app-routing.module';
import  HomeModule  from './home/home.module';
import  AccountModule  from './account/account.module';
import  EntityModule  from './entities/entity.module';
import * as moment from 'moment';
// jhipster-needle-angular-add-module-import JHipster will add new module here
import  JhiMainComponent, NavbarComponent, FooterComponent, PageRibbonComponent, ActiveMenuDirective, ErrorComponent  from './layouts';
@NgModule(
    imports: [
        BrowserModule,
        Ng2Webstorage.forRoot( prefix: 'jhi', separator: '-' ),
        NgJhipsterModule.forRoot(
            // set below to true to make alerts look like toast
            alertAsToast: false,
            alertTimeout: 5000,
            i18nEnabled: true,
            defaultI18nLang: 'en'
        ),
        SharedModule.forRoot(),
        CoreModule,
        HomeModule,
        AccountModule,
        // jhipster-needle-angular-add-module JHipster will add new module here
        EntityModule,
        AppRoutingModule
    ],
    declarations: [JhiMainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent],
    providers: [
        
            provide: HTTP_INTERCEPTORS,
            useClass: AuthInterceptor,
            multi: true
        ,
        
            provide: HTTP_INTERCEPTORS,
            useClass: AuthExpiredInterceptor,
            multi: true
        ,
        
            provide: HTTP_INTERCEPTORS,
            useClass: ErrorHandlerInterceptor,
            multi: true
        ,
        
            provide: HTTP_INTERCEPTORS,
            useClass: NotificationInterceptor,
            multi: true
        
    ],
    bootstrap: [JhiMainComponent]
)
export class AppModule 
    constructor(private dpConfig: NgbDatepickerConfig) 
        this.dpConfig.minDate =  year: moment().year() - 100, month: 1, day: 1 ;
    

这是 core.module 。

import  NgModule, LOCALE_ID  from '@angular/core';
import  DatePipe, registerLocaleData  from '@angular/common';
import  HttpClientModule  from '@angular/common/http';
import  Title  from '@angular/platform-browser';
import locale from '@angular/common/locales/en';
@NgModule(
    imports: [HttpClientModule],
    exports: [],
    declarations: [],
    providers: [
        Title,
        
            provide: LOCALE_ID,
            useValue: 'en'
        ,
        DatePipe
    ]
)
export class CoreModule 
    constructor() 
        registerLocaleData(locale);
    

提前感谢您的帮助。

【问题讨论】:

你能分享你的模块定义吗? 你能否确保你的两个服务都在你的 app.module.ts 文件的 providers 数组中 @O.MeeKoh 不,他们不是因为@Injectable( providedIn: 'root' ) 我不是 100% 确定,但是在使用 providedIn:root 属性时,为了将服务注入另一个服务,您可能会遗漏一些东西。尝试简单地从您的 AccountService 服务中删除 @Injectable() ,然后将其指定到 app.module.ts 提供程序数组中。看看这是否有效 @O.MeeKoh 感谢您的帮助。当我将它添加到 app.module 中时它可以工作,但我不知道为什么它不使用 @Injectable( providedIn: 'root' ) 即使两个主题都做同样的工作。 【参考方案1】:

您应该始终在根注入器中提供您的服务,除非 在某些情况下,您希望服务仅在以下情况下可用 消费者导入特定的@NgModule。

尝试在providers : [ ] 中添加您要注入的服务core.module

import  NgModule, LOCALE_ID  from '@angular/core';
import  DatePipe, registerLocaleData  from '@angular/common';
import  HttpClientModule  from '@angular/common/http';
import  Title  from '@angular/platform-browser';
import locale from '@angular/common/locales/en';
@NgModule(
    imports: [HttpClientModule],
    exports: [],
    declarations: [],
    providers: [
        AccountService,
        Title,
        
            provide: LOCALE_ID,
            useValue: 'en'
        ,
        DatePipe
    ]
)
export class CoreModule 
    constructor() 
        registerLocaleData(locale);
    

并在您的 AccountService 中将 @Injectable( providedIn: 'root' ) 替换为 @Injectable()

@Injectable()
export class AccountService 
    private userIdentity: any;
    private authenticated = false;
    private authenticationState = new Subject<any>();
    constructor(private languageService: JhiLanguageService, private sessionStorage: SessionStorageService, private http: HttpClient) 

【讨论】:

谢谢兄弟它可以工作,但我不知道为什么它在这种情况下工作,我认为在 Angular 7 中如果我们使用 provideIn 属性,则无需将服务添加到提供程序中。 @span 这里是link,试图向您解释提供者是如何工作的 感谢您的链接。我一直没有解决我的问题。直到我想起过去使用 var this = that 等的日子......我变得不确定,因为我将普通函数作为回调而不是箭头函数传递。他们有不同的这个范围。希望有人偶然发现这个:) 我认为问题的重点是为什么它不适用于@Injectable( providedIn: 'root' )。这个答案缓解了这个问题背后的问题,但基本上违背了 Angular 文档,即 Beginning with Angular 6.0, the preferred way to create a singleton service is to set providedIn to root on the service's @Injectable() decorator. @RidaeHAMDANI,你知道为什么它不能与 @Injectable( providedIn: 'root' ) 一起使用吗?【参考方案2】:

同样的事情发生在我身上,解决方案是mentioned by the user span

-> 在回调中传递箭头函数而不是常规函数。箭头函数没有自己的this

常规函数和箭头函数的区别here

【讨论】:

这是covered in more details here 我看不到问题中的代码与箭头函数之间的关系。 OP 只谈论constructors,他从不打电话给new LoginService(...) 那么为什么会有上下文问题呢?【参考方案3】:

HttpClient 需要 HttpClientModule。只需导入 AppModule。

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';

import  AppRoutingModule  from './app-routing.module';
import  AppComponent  from './app.component';
import  CoreModule  from './core/core.module';
import  HttpClientModule  from '@angular/common/http';
import  MatTreeModule  from '@angular/material';
import  FormsModule, ReactiveFormsModule  from '@angular/forms';
import  BrowserAnimationsModule  from '@angular/platform-browser/animations';

@NgModule(
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    CoreModule,
    MatTreeModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule //add this as fix, simple
  ],
  providers: [],
  bootstrap: [AppComponent]
)
export class AppModule  

【讨论】:

【参考方案4】:

当我在有问题的服务内部的注入中错误地使用接口而不是类实现时,我遇到了类似的问题。

【讨论】:

以上是关于Angular 7:注入的服务未定义的主要内容,如果未能解决你的问题,请参考以下文章

ReferenceError:注入未定义茉莉花

使用Angular 7获取“无法读取未定义的属性'http'”

TS中的Angular 2访问指令返回未定义

错误类型错误:无法读取 Angular 7 拖放中未定义的属性“长度”

AngularJS 和 Typescript - 注入其他服务的服务未定义

错误 ReferenceError: Angular 电子应用程序中未定义 cv