实例化 Injectable 类时未调用 ngOnInit
Posted
技术标签:
【中文标题】实例化 Injectable 类时未调用 ngOnInit【英文标题】:ngOnInit not being called when Injectable class is Instantiated 【发布时间】:2016-05-08 17:35:27 【问题描述】:为什么Injectable
类被解析后不调用ngOnInit()
?
代码
import Injectable, OnInit from 'angular2/core';
import RestApiService, RestRequest from './rest-api.service';
@Injectable()
export class MovieDbService implements OnInit
constructor(private _movieDbRest: RestApiService)
window.console.log('FROM constructor()');
ngOnInit()
window.console.log('FROM ngOnInit()');
控制台输出
FROM constructor()
【问题讨论】:
【参考方案1】:Lifecycle hooks 与 OnInit()
一样,可用于指令和组件。它们不适用于其他类型,例如您的服务。来自文档:
组件的生命周期由 Angular 自己管理。 Angular 创建它,渲染它,创建和渲染它的子节点,当它的数据绑定属性发生变化时检查它,并在从 DOM 中删除它之前销毁它。
指令和组件实例在 Angular 创建、更新和销毁它们时具有生命周期。
【讨论】:
那么简单地将我的ngOnInit
逻辑移动到Injectable
类的构造函数中?我只记得读过,无论出于何种原因,您都应该将任何逻辑排除在构造函数之外。
@LeviFuller 是的,对于服务,您可以在构造函数中进行初始化,或者更好地创建 init 方法并从构造函数中调用它(以防您稍后需要重置服务)。
不完全是,OnInit 与绑定有关。当您想要等待解析输入值时使用它,因为它们在构造函数中不可用。构造函数可以被多次调用。例如,当您更改路线并加载不同的组件时,它们每次都会“构建”并销毁......
这里还值得注意的是,服务可以多次实例化,具体取决于您将它们包含在providers
数组中的位置。如果你想要一个单例服务,把它放在你的主模块的providers
,如果你想要每个组件的服务,直接把它们添加到组件中。
这并不完全不正确,因为@SBD580 在他的回答中指出,ngOnDestroy
被称为注入服务【参考方案2】:
我不知道所有的生命周期钩子,但至于销毁,ngOnDestroy
实际上在 Injectable 的提供者被销毁时被调用(例如由组件提供的 Injectable)。
来自docs :
当指令、管道或服务被销毁时调用的生命周期钩子。
以防万一有人对破坏感兴趣,请查看this问题:
【讨论】:
不调用ngOnInit
真是太可惜了 :-( 我真的很想做一些透明的延迟初始化魔术。如果可以调用 ngOnDestroy
我不明白为什么 init 不能
【参考方案3】:
注意:此答案仅适用于 Angular 组件和指令,不适用于服务。
当ngOnInit
(和其他生命周期钩子)没有为我的组件触发时,我遇到了同样的问题,并且大多数搜索都把我带到了这里。
问题是我使用的是箭头函数语法 (=>
),如下所示:
class MyComponent implements OnInit
// Bad: do not use arrow function
public ngOnInit = () =>
console.log("ngOnInit");
显然这在 Angular 6 中不起作用。使用非箭头函数语法解决了这个问题:
class MyComponent implements OnInit
public ngOnInit()
console.log("ngOnInit");
【讨论】:
可注入类是服务,而不是组件。 OP 询问服务。尽管从语言 POV 来看您的答案可能是正确的,但它并不能回答这个问题。你应该删除它。 @AndrewPhilips 虽然我的用例与 OP 的用例略有不同,但谷歌搜索“未调用 ngOnInit”会导致人们来到这里。我的这个答案的目标不是帮助 OP,而是帮助其他 70,000 多名可能对ngOnInit
有类似问题的观众。
很公平。我相信我看过 SO Q&A,作者提出问题然后回答他们自己的问题。作为一个新的 Angular 程序员,两周前你的回答会让我感到困惑。从 SO 和 NG 的角度来看,我认为您的答案值得提出自己的问题,因此没有被删除,而是“重新分类”。谁知道?也许它可能会接触到更广泛的受众。干杯。
有道理 - 我编辑了我的答案以明确表示这不适用于服务。【参考方案4】:
一旦我的 dataService 被初始化,我必须调用一个函数,相反,我在构造函数中调用它,这对我有用。
【讨论】:
【参考方案5】:import Injectable, OnInit from 'angular2/core';
import RestApiService, RestRequest from './rest-api.service';
import Service from "path/to/service/";
@Injectable()
export class MovieDbService implements OnInit
userId:number=null;
constructor(private _movieDbRest: RestApiService,
private instanceMyService : Service )
// do evreything like OnInit just on services
this._movieDbRest.callAnyMethod();
this.userId = this.instanceMyService.getUserId()
【讨论】:
这个问题是 "callAnyMethod" 只能是 synchoronous 方法,不能是await
'ed...【参考方案6】:
添加@Sasxa 的回答,
在Injectables
中,您通常可以使用class
,将初始代码放入constructor
而不是使用ngOnInit()
,它可以正常工作。
【讨论】:
以上是关于实例化 Injectable 类时未调用 ngOnInit的主要内容,如果未能解决你的问题,请参考以下文章
退出时未调用Angular AuthGuard CanActivate - Firebase Auth