Subjectのsubscribeとnextのタイミング

angular

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();
}
}