Rxjs наблюдаемый angular 2 при изменении localstorage
Я пытаюсь создать наблюдаемый, который возвращает значения при изменении переменной localStorage. Мой абонент не получает новые значения при внесении изменений в localStorage (или, что самое важное, в переменной памяти).
navbar.component.js
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
/**
* This class represents the navigation bar component.
*/
@Component({
moduleId: module.id,
selector: 'sd-navbar',
templateUrl: 'navbar.component.html',
styleUrls: ['navbar.component.css'],
providers: [UserService]
})
export class NavbarComponent implements OnInit {
loggedIn: boolean;
constructor(private us: UserService) { }
ngOnInit() {
this.us.isLoggedIn().subscribe(loggedIn => {
this.loggedIn = loggedIn;
});
}
}
auth.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { UserService } from '../shared/services/user.service';
/**
* This class represents the lazy loaded AuthComponent.
*/
@Component({
moduleId: module.id,
selector: 'sd-auth',
templateUrl: 'auth.component.html',
styleUrls: ['auth.component.css'],
providers: [UserService]
})
export class AuthComponent implements OnInit {
authParams = {
provider: '',
params: {}
};
constructor(private route: ActivatedRoute, private us: UserService) { }
ngOnInit() {
this.route.params.forEach((param) => {
this.authParams.provider = param.authprovider;
});
this.route.queryParams.forEach((queryParams) => {
this.authParams.params = queryParams;
});
this.us.logIn("google", JSON.stringify(this.authParams));
console.log(JSON.parse(localStorage.getItem('authParams')));
}
}
user.service.ts
// user.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subscriber } from 'rxjs/Subscriber';
@Injectable()
export class UserService {
private loggedIn = false;
private logger = new Observable<boolean>((observer: Subscriber<boolean>) => {
observer.next(this.loggedIn);
});
constructor() {
if (localStorage.getItem('authParams')) {
this.loggedIn = !!JSON.parse(localStorage.getItem('authParams')).params.id_token;
} else {
this.loggedIn = false;
}
}
logIn(provider: string, providerResponse: string) {
localStorage.setItem('authParams', providerResponse);
this.loggedIn = true;
}
isLoggedIn(): Observable<boolean> {
return this.logger;
}
logOut() {
localStorage.removeItem('authParams');
this.loggedIn = false;
}
}
Поток выглядит как
Шаг 1- Navbar подписывается на UserService (получает значение по умолчанию loggedIn = false)
Шаг 2 - AuthComponent обновляет UserService (устанавливает loggedIn = true)
Моя подписка в Navbar не обновляется. Что мне здесь не хватает. Нужно ли мне что-то помещать в методе logIn UserService, таком как эмиттер событий?
Ответы
Ответ 1
То, что вы хотите, это предмет. Проверьте документы здесь (https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/subjects/subject.md)
Для быстрого примера, что-то вроде этого:
export class UserService {
...
private logger = new Subject<boolean>();
...
isLoggedIn(): Observable<boolean> {
return this.logger.asObservable();
}
logIn(provider: string, providerResponse: string) {
localStorage.setItem('authParams', providerResponse);
this.loggedIn = true;
this.logger.next(this.loggedIn);
}
logOut() {
localStorage.removeItem('authParams');
this.loggedIn = false;
this.logger.next(this.loggedIn);
}
...
Ответ 2
Чтобы быть более точным, используйте BehaviourSubject из
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
Для ex:
@Injectable()
export class UserService {
public username = new BehaviorSubject<string>('');
public preferredLanguage = new BehaviorSubject<string>('');
public preferredTimezone = new BehaviorSubject<string>('');
constructor(
private router: Router,
private jwtTokenService: JwtTokenService
) {
let token: string = localStorage.getItem('token'); // handled for page hard refresh event
if (token != null) {
this.decode(token);
}
}
private decode(token: string) {
let jwt: any = this.jwtTokenService.decodeToken(token);
this.username.next(jwt['sub']);
this.preferredLanguage.next(jwt['preferredLanguage']);
this.preferredTimezone.next(jwt['preferredTimezone']);
}
public setToken(token: any) {
localStorage.setItem('auth_token', token);
this.decode(token);
}
}
и узнать разницу между BehaviorSubject и Observable:
Angular 2 - Предмет поведения vs Наблюдаемый?
Ответ 3
Альтернатива - наблюдать событие storage
fromEvent(window, 'storage').subscribe((storageEvent) => {
//do what you need to do with your storageEvent
})
Это означает, что вам не нужно оборачивать нативный API на любом слое сервиса.