尽管使用 @Injectable(providedIn: 'root' ) 装饰器,Angular Service 在注入组件时不充当单例

Posted

技术标签:

【中文标题】尽管使用 @Injectable(providedIn: \'root\' ) 装饰器,Angular Service 在注入组件时不充当单例【英文标题】:Angular Service not acting as singleton when injected in components despite using @Injectable(providedIn: 'root' ) decorator尽管使用 @Injectable(providedIn: 'root' ) 装饰器,Angular Service 在注入组件时不充当单例 【发布时间】:2021-01-01 07:16:09 【问题描述】:

我有一个项目,其中包含两个模块(默认 AppModule 和创建项目时由 angular cli 生成的路由模块),我创建的两个组件和一个注入每个组件的构造函数的服务。我希望拥有相同的服务实例(每次注入服务时都是单例,因为它具有 @Injectable(providedIn: 'root' ) 装饰器)但每次导航时我都会不断获得一个全新的服务实例到我的每个组件。下面是我的代码:

app.module.html

\<router-outlet\>\</router-outlet\>

app.module.ts

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

import  AppRoutingModule  from './app-routing.module';
import  AppComponent  from './app.component';
import  TestComponent  from './test/test.component';
import  Test2Component  from './test2/test2.component';


@NgModule(
  declarations: [
    AppComponent,
    TestComponent,
    Test2Component
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
)
export class AppModule  

app-routing.module.ts

import  NgModule  from '@angular/core';
import  Routes, RouterModule  from '@angular/router';
import  TestComponent  from './test/test.component';
import  Test2Component  from './test2/test2.component';

const routes: Routes = [
   path: 'test1', component: TestComponent ,
   path: 'test2', component: Test2Component 
];

@NgModule(
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
)
export class AppRoutingModule  

test.component.ts

import  Component from '@angular/core';
import  TestService  from '../test.service';

@Component(
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
)
export class TestComponent 

  constructor(private _testService: TestService)  

test2.component.ts

import  Component  from '@angular/core';
import  TestService  from '../test.service';

@Component(
  selector: 'app-test2',
  templateUrl: './test2.component.html',
  styleUrls: ['./test2.component.css']
)
export class Test2Component 

  constructor(private _testService: TestService)  


test.service.ts

import  Injectable  from '@angular/core';

@Injectable(
  providedIn: 'root'
)
export class TestService 

  private date = new Date();

  constructor() 
    console.log("Inside the service ", this.date);
  


【问题讨论】:

【参考方案1】:

像这样在 app.module.ts 中的 providers 数组中提供您的测试服务。创建单例。 提供者:[TestService]

【讨论】:

不需要。 “从 Angular 6.0 开始,创建单例服务的首选方法是在服务的 @Injectable() 装饰器上将 providedIn 设置为 root。”来自:angular.io/guide/…【参考方案2】:

参考以下链接: https://www.w3resource.com/angular/angular-singleton-service.php

您需要在 app.module.ts 中将您的服务注册为提供者。

providers: [provide: Service]

【讨论】:

不需要。 “从 Angular 6.0 开始,创建单例服务的首选方法是在服务的 @Injectable() 装饰器上将 providedIn 设置为 root。”来自:angular.io/guide/…【参考方案3】:

从代码的外观来看,您的服务确实是单例的。

将其插入 app.component.html,然后尝试链接:

<nav>
  <ul>
    <li><a routerLink="child-a">Child A</a></li>
    <li><a routerLink="child-b">Child B</a></li>
  </ul>
</nav>

我怀疑您尝试通过在浏览器导航栏中写入 url 来检查这两个组件,因此在您认为要重新路由时重新加载应用程序。是这样吗?

我创建了一个路由和单例服务使用示例here。

可以看到,点击几次后,构造函数在控制台中只运行了一次:

【讨论】:

谢谢。您的解决方案对我来说很好。我想这是因为我没有使用路由器模块。相反,我使用浏览器 url 栏和重新加载按钮来更改 url。这会导致应用程序每次都重新加载,并且我的所有服务都会被重新实例化。因此,当我们在导航栏中分配一个 url 并按 Enter 键时,我们向服务器发出请求以再次获取 index.html 文件,这意味着应用程序再次被重新引导。

以上是关于尽管使用 @Injectable(providedIn: 'root' ) 装饰器,Angular Service 在注入组件时不充当单例的主要内容,如果未能解决你的问题,请参考以下文章

Angular Provider 之 useFactory

Angular Multi Provider 依赖顺序

无法解析 Class: (?) 的所有参数,尽管已提供

尽管ui-route和provider似乎工作正常,但我无法在angularjs中加载视图......这是一段代码

使用相同服务的多个实例

使用同一服务的多个实例