Subjectにnextしても、subscribeされずデータが取れない!と散々悩みました。
まずはその時のコードを。
src/app/shared/service/session.service.ts
import { Injectable } from '@angular/core'; import { Observable, Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SessionService { public sessionSubject = new Subject<any>(); public sessionState = this.sessionSubject.asObservable(); constructor( ) { } checkSession() { // ① this.sessionSubject.next(false); // ② this.checkSessionInfo().subscribe(result => { this.sessionSubject.next(true); }); } checkSessionInfo(): Observable<any> { // セッションが有効か判定 } }
src/app/login/login.component.ts
import { Component, OnInit } from '@angular/core'; import { SessionService } from '../shared/service/session.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { constructor(private sessionService: SessionService) { } ngOnInit() { this.sessionService.checkSession(); this.sessionService.sessionState.subscribe( (result) => { console.log(result); }); } }
session.service.ts
の①の場所でnextしたらsubscribeされず、②の場所でnextしたらsubscribeされデータが取れる。
なぜ…?
調べても似たような情報があまり見つからず、わりと諦めかけてました。
で、やっと見つけましたこちらの記事。
Angular subject subscription is not working – Stack Overflow
this.sessionService.sessionState.subscribe
と
this.sessionService.checkSession();
の記述順番が問題だったんですね。
this.sessionService.checkSession();
が先に書いてあったため、
this.sessionService.sessionState.subscribe
で購読準備をする前に、
①のnextでデータを流してるから、①はsubscribeできなかった。
②はサーバー側と通信してる間に、login.component.ts
でsubscribeが呼び出されたため、たまたまsubscribeの準備→nextという順で処理されてデータが取得できた。
ということだったんですね。
なので、login.component.ts
をこう書き換えたら解決でした!
import { Component, OnInit } from '@angular/core'; import { SessionService } from '../shared/service/session.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) export class LoginComponent implements OnInit { constructor(private sessionService: SessionService) { } ngOnInit() { // ここの順番!! this.sessionService.sessionState.subscribe( (result) => { console.log(result); }); this.sessionService.checkSession(); } }