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 只谈论constructor
s,他从不打电话给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:注入的服务未定义的主要内容,如果未能解决你的问题,请参考以下文章
使用Angular 7获取“无法读取未定义的属性'http'”
错误类型错误:无法读取 Angular 7 拖放中未定义的属性“长度”