Angular 中的服务被销毁时
封面照片由 Asa Rodger 拍摄,来自 Unsplash
如果我们阅读Angular OnDestroy生命周期钩子 API 的描述,就会发现它可以用于服务。
但除此之外,我们找不到更多信息。如果我们查看生命周期钩子页面,会发现上面没有任何解释,所以是时候自己尝试一下了。
我们如何使用服务?
首先,我们将深入探讨服务的使用方式。服务可以通过不同的方式提供给应用程序:
根级别
该服务对所有人开放,每个模块都可以使用此根服务。它以单例模式提供,因此仅存在一次,并且对该服务的所有操作、所有可观察对象都在整个应用程序中共享。
可以通过两种方式定义它。使用 providedIn 时,您无需在模块中提供它。
@Injectable({ providedIn: 'root'})
export class RootService { ... }
关于提供的旁注:
您也可以使用
provideIn: module,但这仍处于实验阶段,所以请谨慎使用,providedIn: 'root'它是一个很好的集成工具。
或者将其注入到根模块中
@Injectable()
export class RootService { ... }
@NgModule({
providers: [ RootService ],
})
export class AppModule{}
模块层面
我们还可以在模块级别创建服务,这些服务是私有的,专用于特定的模块。它们的逻辑仅在该模块内部共享。
@Injectable()
export class ModuleService { ... }
@NgModule({
providers: [ ModuleService ],
})
export class MyCustomModule{}
在组件层面
这些服务是在组件级别注入的,因此只有在组件运行期间它们才会存在。
// providedIn
@Injectable()
export class Componentervice { ... }
@Component({
selector: 'my-component',
template: '...',
providers: [ Componentervice ],
})
export class MyComponent{}
服务的生命周期。
首先,我们关注的是服务何时被创建。我们可以为此添加一个简单的测试。只需编写类似下面的代码即可:
export class MyService {
constructor(){
console.log('constructor initialized')
}
}
为了测试这个逻辑,我们有一些测试用例,需要在服务上创建服务。
- 根级
- 模块级别
- 延迟加载模块
- 组件级
初始化服务
所有服务均在首次使用时初始化。
关于服务的补充说明。仅仅提供服务是不够的,我们还需要实际执行一些操作来初始化该服务,因此将其添加到提供者数组中并不能初始化该服务。我们可以通过不同的方式首次使用该服务,例如通过组件或工厂来使用它……
因此,我们可以确定,所有服务都会在首次使用时初始化。
这也意味着,延迟加载的服务仅在路由首次加载时初始化,`providedIn: 'root'` 服务仅在首次使用时初始化,……
我们来看一下输出结果,这里出现了一个有趣的模式。正如预期的那样,根服务提供者、模块服务提供者和延迟加载服务提供者都只创建了一次。当我们重新创建组件时,服务不会再次创建。


但最有趣的部分是组件提供的服务:每次创建组件时,服务也会同时创建。
每次创建组件时,只会创建组件提供程序。
销毁服务
现在我们做同样的事情,但这次我们使用 ngOnDestroy 钩子来销毁服务。
出于某些原因,我们在 Google 中勾选了“保留日志”复选框,这样即使我们离开页面,也能跟踪日志历史记录。
同样,每个服务的测试代码都类似。
@Injectable()
export class MyService implements OnDestroy {
name = 'xxx service';
constructor(private counterService: CounterService) {
console.log('Construct the xxx service')
}
ngOnDestroy() {
console.log('Destroy the xxx service')
}
}
首先我们来看组件服务,由于每次创建组件服务时都会创建组件服务,我们期望组件销毁时组件服务也会销毁。
如果我们查看其他三项服务,就会发现它们永远不会被销毁。即使我们离开页面也不会。虽然您在离开页面时可能会意外获得它们,但这并不能保证一定如此。
所以关于 ngOnDestroy hook 的结论是:
结论
- 除非您在组件级别提供服务,否则您永远无法确定服务是否已被销毁。
- 如果你提供的是组件级别的服务,并且你重构了代码,那么你需要注意这一点。
在服务中使用此钩子时要小心
完整的试用版可在 StackBlitz 上找到: