即使@Injectable已providIn:'root',服务也会创建另一个实例。我如何确保服务是单例的?

Pat*_*ung 4 ionic-framework angular ionic4

我有 2 个服务位于 /services、AccountService 和 AuthenticationService。我还有 2 个页面:accounts.page 和 add-accounts.page 位于 /accounts 中,add-accounts.page 位于 /accounts/add-accounts 中。\n我在accounts.page 和 add- 中都使用 AccountService account.page 从本地 json 加载帐户并将其存储在 Ionic/Storage 中。因此计划是使用该服务从存储中获取帐户并添加新帐户。我在服务中有一个 ReplaySubject 来检测新的更改,我想在帐户 html 页面中使用它来显示帐户数组。\n我正在使用 Ionic 4 和 Angular 版本 7

\n

经过一番修改后,我发现该服务获得了 2 个实例,因此我没有向最初开始使用的 ReplaySubject 添加新的更改。我通过将 console.log 添加到服务的构造函数中发现了这一点,并在控制台中查看,从帐户页面转到添加帐户页面后,我发现了同一 console.log 的 2 个实例。因此,我在添加帐户页面中对 accountService 所做的更改是另一个实例,并且在第一个实例中没有更改。

\n

当我使用其他服务(AuthenticationService)对此进行测试时,我在控制台中没有得到 2 个 console.log 输出。 \n我仔细检查了 @Injectable 装饰器,如果它们具有 \xc2\xa0providedIn 的正确语法:'root'\xc2\ xa0 并在测试删除 \xc2\xa0providedIn: 'root'\xc2\xa0part 的旧角度方法并将服务导入 \xc2\xa0app.module.ts\xc2\xa0 并将其添加到 \xc2\xa0providers\xc2\ xa0array 我收到 a\xc2\xa0NullInjectorError: Noprovider for AccoutService\xc2\xa0Error 我无法解决。

\n

我尝试创建一个新服务并ionic g service services/newService创建一个输出一些文本的函数。我还创建了一个 BehaviourSubject 来查看和跟踪状态更改。它看起来像这样:

\n
import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class NewAccoutService {\n\n  authenticationState = new BehaviorSubject(false);\n  constructor() {\n    this.authenticationState.next(true);\n    console.log('This text should only happen once');\n  }\n  consoleLog() {\n    console.log('did it work?');\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我还尝试做的是创建一个新的空白离子项目并创建 2 个页面和 2 个服务。在该项目中,它们的行为与应有的一样,只被创建一次。

\n

与我的同事交谈后,他们建议创建一个具有相同文件结构的新测试项目,并将代码复制/粘贴到新项目中,这可能会解决问题,因为某些文件可能未创建。然而这并没有成功,所以可能还有其他问题。

\n

帐户.服务.ts

\n

这是AccountService的相关代码

\n
import { Injectable } from '@angular/core';\n@Injectable(\n  { providedIn: 'root' }\n)\nexport class AccountService {\n  changed: ReplaySubject<Account[]> = new ReplaySubject(1);\nconstructor(\n    private http: HttpClient,\n    private storage: Storage\n  ) {\n    console.log('Account Service constructor Text');\n    // some other code\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

帐户.page.ts

\n

这是帐户页面的相关代码

\n
import { AccountService } from '../services/account.service.js';\nimport { AuthenticationService } from '../services/authentication.service.js';\n@Component({\n  selector: 'app-accounts',\n  templateUrl: './accounts.page.html',\n  styleUrls: ['./accounts.page.scss'],\n})\nexport class AccountsPage implements OnInit,OnDestroy {\n  accounts: Account[] = [];\n  accountsLoaded = false;\n  subscription: any;\nconstructor(private http: HttpClient,\n    private accountService: AccountService,\n    private router: Router,\n    private authService: AuthenticationService,\n    private changeRef: ChangeDetectorRef,\n    private testService: NewAccoutService) {\n         \n    }\nngOnInit() {\n    this.testService.authenticationState.next(false);\n    console.log('Test Service state: ', this.testService.authenticationState.value);\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

添加帐户.page.ts

\n

这是添加帐户页面的相关代码

\n
import { AccountService } from '../../services/account.service';\nimport { AuthenticationService } from '../../services/authentication.service';\n@Component({\n  selector: 'app-add-accounts',\n  templateUrl: './add-accounts.page.html',\n  styleUrls: ['./add-accounts.page.scss'],\n})\nexport class AddAccountsPage implements OnInit {\npublic account: FormGroup;\n  public currentSliderValue: number = 1;\nconstructor(  private platform: Platform,\n                private changeRef: ChangeDetectorRef,\n                private router: Router,\n                private accountService: AccountService,\n                private authentication: AuthenticationService,\n                private testService: NewAccoutServiceService ) {\nthis.testService.authenticationState.next(false);\n    console.log('Test Service state: ', this.testService.authenticationState.value);\n}\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

当我加载帐户页面时,我希望看到以下内容:

\n

预期结果:当我加载accounts.page时,我想看到console.log消息。this.testService.authenticationState.valuefalse

\n

当我从accounts.page 转到add-accounts 时,AccountService 中的console.log 不应再次调用。this.testService.authenticationState.valuetrue

\n

实际结果:加载到 account.page 我看到 console.log 消息并且this.testService.authenticationState.valuefalse。从 account.page 加载到 add-accounts.page 我收到另一个构造函数 console.log 消息也this.testService.authenticationState.value仍然是false

\n

由于我对 Ionic 和 Angular 还很陌生,所以我已经没有什么可以尝试的选择了。每个服务都应该作为单例工作,但不知怎的却不起作用。如果您需要额外的代码来帮助我解决此问题,请告诉我。

\n

编辑:

\n

我找到了非常愚蠢的解决方案。VS Code 在某一时刻生成了accounts.page.ts 中我的服务的导入,并且出于某种未知的原因它.js在文件位置之后添加了我的意思是看看这个比较。

\n

import { AuthenticationService } from '../services/authentication.service';

\n

import { AuthenticationService } from '../services/authentication.service.js';

\n

在工作中查看我的代码的 3 个人中没有一个发现这个问题。直到今天,在又花了 3 个小时尝试一切并非常仔细地查看代码后,我和我的同事想到了一个导入问题,突然我想到“为什么导入中有一个 .js,这是不对的”。

\n

Pat*_*ung 5

我找到了解决方案

对于任何遇到此错误的人。在 VS Code 生成的导入中,文件位置后面有一个 .js 扩展名。

前:

import { AuthenticationService } from '../services/authentication.service.js';

后:

import { AuthenticationService } from '../services/authentication.service';

删除此扩展后,它可以正常工作。我不知道为什么 VS Code 只在我的 account.page.ts 中执行了一次,但这是另一个问题,但不再发生了。