[英]rxjs observable angular 2 on localstorage change
我正在尝试创建一个 observable,它在 localStorage 变量发生更改时返回值。 我的订阅者在更改 localStorage 时没有获得新值(或者就此而言是内存变量)。
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;
});
}
}
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
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(获取默认值 login=false) 第 2 步 - AuthComponent 更新 UserService(设置 loggingIn = true)
我在导航栏中的订阅没有更新。 我在这里错过了什么。 我是否需要在 UserService 的 logIn 方法中放一些东西,比如事件发射器?
你想要的是一个主题。 在此处查看文档。
举个简单的例子,像这样:
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);
}
...
我写了一个 StorageService 来支持 Observable localStorage 和 sessionStorage。 它支持一项服务。
存储服务
import { BehaviorSubject, Observable } from 'rxjs';
/**
* Storage service
* used for persist application data in observable key value pair
*/
export class StorageService {
private storage: Storage;
private subjects: Map<string, BehaviorSubject<any>>;
/**
* Constructor with service injection
* @param storage
*/
constructor(storage: Storage) {
this.storage = storage;
this.subjects = new Map<string, BehaviorSubject<any>>();
}
/**
* watch data of given key
* @param key
* @param defaultValue
*/
watch(key: string): Observable<any> {
if (!this.subjects.has(key)) {
this.subjects.set(key, new BehaviorSubject<any>(null));
}
var item = this.storage.getItem(key);
if (item === "undefined") {
item = undefined;
} else {
item = JSON.parse(item);
}
this.subjects.get(key).next(item);
return this.subjects.get(key).asObservable();
}
/**
* get data of given key
* @param key
*/
get(key: string): any {
var item = this.storage.getItem(key);
if (item === "undefined") {
item = undefined;
} else {
item = JSON.parse(item);
}
return item;
}
/**
* set value on given key
* @param key
* @param value
*/
set(key: string, value: any) {
this.storage.setItem(key, JSON.stringify(value));
if (!this.subjects.has(key)) {
this.subjects.set(key, new BehaviorSubject<any>(value));
} else {
this.subjects.get(key).next(value);
}
}
/**
* remove given key
* @param key
*/
remove(key: string) {
if (this.subjects.has(key)) {
this.subjects.get(key).complete();
this.subjects.delete(key);
}
this.storage.removeItem(key);
}
/**
* clear all available keys
*/
clear() {
this.subjects.clear();
this.storage.clear();
}
}
本地存储服务
import { Injectable, Inject } from '@angular/core';
import { StorageService } from './storage.service';
/**
* Local storage service
* used for persist application data in observable key value pair
*/
@Injectable()
export class LocalStorageService extends StorageService {
/**
* Constructor with service injection
* @param window
*/
constructor(@Inject('WINDOW') private window: any) {
super(window.localStorage);
}
}
会话存储服务
import { Injectable, Inject } from '@angular/core';
import { StorageService } from './storage.service';
/**
* Session storage service
* used for persist application data in observable key value pair
*/
@Injectable()
export class SessionStorageService extends StorageService {
/**
* Constructor with service injection
* @param window
*/
constructor(@Inject('WINDOW') private window: any) {
super(window.sessionStorage);
}
}
您可以通过以下方式使用该服务:
import { LocalStorageService } from './local-storage.service';
export class TestClass implements OnInit, OnDestroy {
constructor(
private localStorage: LocalStorageService,
) { }
ngOnInit() {
// get current value
this.localStorage.get('foo');
// set new value
this.localStorage.set('foo', 'bar');
// watch value changes
this.localStorage.watch('foo').pipe(takeUntil(this.unsubscribe)).subscribe(foo => console.log('foo changed', foo));
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
}
(我真的是 TypeScript 的新手,有几个月的经验。欢迎提出任何改进建议:-))
另一种方法是观察storage
事件
fromEvent(window, 'storage').subscribe((storageEvent) => {
//do what you need to do with your storageEvent
})
这意味着您不需要将本机 API 包装在任何服务层中。
更准确地说,使用 BehaviourSubject from import { BehaviorSubject } from 'rxjs/BehaviorSubject';
例如:
@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 之间的区别: BehaviorSubject vs Observable?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.