我在/ services,AccountService和AuthenticationService中有2个服务。我也有2页:位于/ accounts中的account.page和add-accounts.page和位于/ accounts / add-accounts中的add-accounts.page。 我在account.page和add-accounts.page中都使用AccountService,它们从本地json加载帐户并将其存储在Ionic / Storage中。因此,计划是使用服务从存储中获取帐户并添加新帐户。我在服务中有一个ReplaySubject来检测要在帐户html页面中使用的新更改,以显示帐户数组。 我在Angular 7中使用Ionic 4
修改之后,我发现该服务正在获得2个实例,因此我不会对最初开始的ReplaySubject添加新的更改。通过将console.log添加到我的服务的构造函数中,并从帐户页面转到添加帐户页面后,在控制台中查看,我发现了同一console.log的2个实例。因此,我对add-accounts页面中的accountService所做的更改是另一个实例,并且在第一个实例中没有更改。
当我用其他服务(AuthenticationService)测试它时,在控制台中没有得到2 console.log输出。 我仔细检查了@Injectable装饰器是否具有providedIn:'root'的正确语法,并测试了删除providedIn:'root'部分并将其导入app.module.ts并将其添加到provider数组,我得到一个NullInjectorError:没有我无法解决的AccoutService错误提供程序。
我尝试使用ionic g service services/newService
创建一个新服务,并制作了一个输出一些文本的函数。我还创建了一个BehaviourSubject来查看和跟踪状态更改。看起来像这样:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class NewAccoutService {
authenticationState = new BehaviorSubject(false);
constructor() {
this.authenticationState.next(true);
console.log('This text should only happen once');
}
consoleLog() {
console.log('did it work?');
}
}
我还试图做的是创建一个新的空白离子项目,并创建了2页和2个服务。在该项目中,它们的行为与预期的一样,只创建了一次。
与同事交谈后,他们建议创建一个具有相同文件结构的新测试项目,并将代码复制/粘贴到新项目中,这可能会解决问题,因为可能未创建某些文件。但是,此操作无法解决,因此可能还有其他问题。
这是AccountService的相关代码
import { Injectable } from '@angular/core';
@Injectable(
{ providedIn: 'root' }
)
export class AccountService {
changed: ReplaySubject<Account[]> = new ReplaySubject(1);
constructor(
private http: HttpClient,
private storage: Storage
) {
console.log('Account Service constructor Text');
// some other code
}
}
以下是“帐户页面”的相关代码
import { AccountService } from '../services/account.service.js';
import { AuthenticationService } from '../services/authentication.service.js';
@Component({
selector: 'app-accounts',
templateUrl: './accounts.page.html',
styleUrls: ['./accounts.page.scss'],
})
export class AccountsPage implements OnInit,OnDestroy {
accounts: Account[] = [];
accountsLoaded = false;
subscription: any;
constructor(private http: HttpClient,
private accountService: AccountService,
private router: Router,
private authService: AuthenticationService,
private changeRef: ChangeDetectorRef,
private testService: NewAccoutService) {
}
ngOnInit() {
this.testService.authenticationState.next(false);
console.log('Test Service state: ', this.testService.authenticationState.value);
}
}
这是添加帐户页面的相关代码
import { AccountService } from '../../services/account.service';
import { AuthenticationService } from '../../services/authentication.service';
@Component({
selector: 'app-add-accounts',
templateUrl: './add-accounts.page.html',
styleUrls: ['./add-accounts.page.scss'],
})
export class AddAccountsPage implements OnInit {
public account: FormGroup;
public currentSliderValue: number = 1;
constructor( private platform: Platform,
private changeRef: ChangeDetectorRef,
private router: Router,
private accountService: AccountService,
private authentication: AuthenticationService,
private testService: NewAccoutServiceService ) {
this.testService.authenticationState.next(false);
console.log('Test Service state: ', this.testService.authenticationState.value);
}
}
当我加载帐户页面时,我希望看到以下内容:
预期结果:当我加载account.page时,我想查看console.log消息。 this.testService.authenticationState.value
是false
。
当我从accounts.page转到添加帐户时,应该不再次调用AccountService的console.log。 this.testService.authenticationState.value
是true
。
实际结果:正在加载到account.page中,我看到console.log消息,并且this.testService.authenticationState.value
是false
。从accounts.page加载到add-accounts.page,我得到另一个构造函数console.log消息,this.testService.authenticationState.value
仍然是false
由于我还是Ionic和Angular的新手,所以我没有其他选择。每个服务应该都可以单例运行,但是某种程度上是行不通的。让我知道您是否需要其他代码来帮助我解决此问题。
我发现解决方案太愚蠢了。 VS Code在某一时刻生成了我的服务在account.page.ts中的导入,由于某种未知原因,它在文件位置之后添加了.js
,我的意思是看一下这种比较。
import { AuthenticationService } from '../services/authentication.service';
import { AuthenticationService } from '../services/authentication.service.js';
在工作中查看我的代码的3个人中没有一个发现此问题。直到今天,又经过3个小时的尝试并仔细地查看代码,我和我的同事和我突然想到了一个导入问题:“为什么导入中存在.js,这是不对的。”
答案 0 :(得分:1)
对于任何以某种方式遇到此错误的人。在我的VS Code生成的导入文件中,文件位置后有一个.js扩展名。
之前:
import { AuthenticationService } from '../services/authentication.service.js';
之后:
import { AuthenticationService } from '../services/authentication.service';
删除此扩展名后,它应该可以正常工作。我不知道为什么VS Code一次只在我的account.page.ts中做到这一点,但这是另一个不再出现的问题。
答案 1 :(得分:0)
对于想要在任何地方获得主题价值的地方,都需要通过可观察的方式订阅主题。
@Injectable({
providedIn: 'root'
})
export class Service {
randomSubject = new BehaviorSubject(initialValue);
randomObservable = authenticationStateSubject.asObservable();
}
然后在您的组件中,您需要在Init上订阅它。
export class RandomComponent implements OnInit {
constructor(private service: Service) {}
ngOnInit(): void {
this.service.randomObservable.subscribe(randomValue => console.log(randomValue));
}
}
每次分配新值时,订阅回调中的任何事情都会发生。
要更新其值,请在主题上调用next并传递一个值。
this.service.randomSubject.next(newValue);
不过,请注意,如果您打算执行Http请求以检索本地JSON,我将使用ReplaySubject代替b / c,而不必使用值初始化主题。
答案 2 :(得分:0)
如果使用延迟加载模块,则该服务可能会出现在延迟加载的模块提供程序中。
答案 3 :(得分:0)
providers
中删除我有类似的问题(我尝试在单例服务中共享 rxjs 流)。我使用以下代码测试 angular 创建了许多理论上单例服务 (LoginService) 的实例:
private timestamp = +new Date();
constructor() {
this.timestamp = +new Date();
console.log('constructor: ' + this.timestamp);
}
public getTimestamp() {
return this.timestamp;
}
在不同的页面中,我打印了 getTimestamp()。在控制台中,我看到构造函数运行了多次(但理论上对于单例它应该只运行一次)。
在那一点上,我发现我将我的 LoginService 放在了许多组件的 providers 部分 - 这就是为什么 angular 创建多个单例服务实例的原因 - 在删除所有之后 - 它创建了一个 :)
@Component({
selector: '...',
providers: [LoginService, ...], // REMOVE this service from all components
styleUrls: [...],
templateUrl: '...',
})