使用 Angular Observable 订阅 Session Storage key
Using Angular Observable to subscribe to Session Storage key
我正在尝试完成我希望的简单“查看会话存储中的密钥并在它发生变化时更新它”的场景,但 Observables 真的让我失望。
message$ = new Observable(observer => {
observer.next(window.sessionStorage.getItem('message'));
});
ngOnInit() {
this.message$.subscribe();
}
并且消息 $ 绑定到 HTML,非常简单:
<p id="message">{{message$ | async}}</p>
如果 'message' 中已经存储了值,那么 Observable
会将文本输出到 HTML
,但是如果在 init 上没有消息然后它被添加,或者消息值确实存在并已更新,没有任何反应。我显然做错了什么,我很感激 Observables
.
知识渊博的人的见解
因为你使用的是异步管道,所以你不需要在你的组件中订阅,你可以把它去掉。 AsyncPipe 将在幕后处理订阅/取消订阅。
尝试改用主题。
// This is what will help you broadcast your message and push updates to subscribers.
message$ = new Subject();
// Anytime the "message" changes, you'll want to call this.
updateTheSubject() {
this.message$.next(window.sessionStorage.getItem('message'));
}
您的 html 模板可以保持不变。
我想你要找的是 StorageEvent
您可以使用 fromEvent 从该事件创建您的可观察对象,如下所示:
const message$ = fromEvent<StorageEvent>(window, "storage").pipe(
filter(event => event.storageArea === sessionStorage),
filter(event => event.key === "message"),
map(event => event.newValue)
);
请注意,我添加了过滤器以专门查找 sessionStorage 的更新,并且我指定了密钥 === "message",但您也可以使用 localStorage 和任何您想要的密钥
此外,与 一样,如果您打算仅在模板中使用它,则无需订阅此 observable。
已编辑: 上述解决方案仅在您打开多个选项卡并希望同步存储更改时有效。检查 this answer
我认为你必须改变一个地方,你将你的值设置为sessionStorage。我的建议是使用您自己的 StorageService (my example),您可以在其中将您的值设置为存储并保留一个可观察对象,它应该在您设置 key/value.
时发出
这个帖子有点旧,但我刚遇到同样的问题。
正如@quake 所指出的,在同一 window.
内的更改不会引发 storageEvent
要实现所需的“设置拦截”,您必须修补 localSorage 或 sessionStorage 的存储功能。例如:
// somewhere in a Class...
private setStorageItemFunc: (key: string, value: string) => void;
private getStorageItemFunc: (key: string) => string;
private subject$: Subject<string>;
applySettingsInterception() {
// define a Subject
this.subject$ = new Subject();
// just for demonstation purposes. Don't subscribe to the subject, use async pipe instead
this.subject$.subscribe(e => {
console.log('value changed', e);
});
// save original functions
this.setStorageItemFunc = window.localStorage.setItem;
this.getStorageItemFunc = window.localStorage.getItem;
// set storage functions to the newly created interceptor functions
// bind to this to get access to the current object and it's values in interceptor function
window.localStorage.setItem = this.setStorageItem.bind(this);
window.localStorage.getItem = this.getStorageItem.bind(this);
}
private setStorageItem(key: string, value: string): void {
console.log('setStorageItem', key, value);
this.subject$.next(`${key}: ${value}`);
this.setStorageItemFunc.call(localStorage, key, value);
}
private getStorageItem(key: string): string {
const value = this.getStorageItemFunc.call(localStorage, key);
console.log('getStorageItem', key, value);
return value;
}
如您所见,在截获的函数中,您可以调用@damian-c.
提到的Subject的next()
函数
我正在尝试完成我希望的简单“查看会话存储中的密钥并在它发生变化时更新它”的场景,但 Observables 真的让我失望。
message$ = new Observable(observer => {
observer.next(window.sessionStorage.getItem('message'));
});
ngOnInit() {
this.message$.subscribe();
}
并且消息 $ 绑定到 HTML,非常简单:
<p id="message">{{message$ | async}}</p>
如果 'message' 中已经存储了值,那么 Observable
会将文本输出到 HTML
,但是如果在 init 上没有消息然后它被添加,或者消息值确实存在并已更新,没有任何反应。我显然做错了什么,我很感激 Observables
.
因为你使用的是异步管道,所以你不需要在你的组件中订阅,你可以把它去掉。 AsyncPipe 将在幕后处理订阅/取消订阅。
尝试改用主题。
// This is what will help you broadcast your message and push updates to subscribers.
message$ = new Subject();
// Anytime the "message" changes, you'll want to call this.
updateTheSubject() {
this.message$.next(window.sessionStorage.getItem('message'));
}
您的 html 模板可以保持不变。
我想你要找的是 StorageEvent
您可以使用 fromEvent 从该事件创建您的可观察对象,如下所示:
const message$ = fromEvent<StorageEvent>(window, "storage").pipe(
filter(event => event.storageArea === sessionStorage),
filter(event => event.key === "message"),
map(event => event.newValue)
);
请注意,我添加了过滤器以专门查找 sessionStorage 的更新,并且我指定了密钥 === "message",但您也可以使用 localStorage 和任何您想要的密钥
此外,与
已编辑: 上述解决方案仅在您打开多个选项卡并希望同步存储更改时有效。检查 this answer
我认为你必须改变一个地方,你将你的值设置为sessionStorage。我的建议是使用您自己的 StorageService (my example),您可以在其中将您的值设置为存储并保留一个可观察对象,它应该在您设置 key/value.
时发出这个帖子有点旧,但我刚遇到同样的问题。
正如@quake 所指出的,在同一 window.
内的更改不会引发 storageEvent要实现所需的“设置拦截”,您必须修补 localSorage 或 sessionStorage 的存储功能。例如:
// somewhere in a Class...
private setStorageItemFunc: (key: string, value: string) => void;
private getStorageItemFunc: (key: string) => string;
private subject$: Subject<string>;
applySettingsInterception() {
// define a Subject
this.subject$ = new Subject();
// just for demonstation purposes. Don't subscribe to the subject, use async pipe instead
this.subject$.subscribe(e => {
console.log('value changed', e);
});
// save original functions
this.setStorageItemFunc = window.localStorage.setItem;
this.getStorageItemFunc = window.localStorage.getItem;
// set storage functions to the newly created interceptor functions
// bind to this to get access to the current object and it's values in interceptor function
window.localStorage.setItem = this.setStorageItem.bind(this);
window.localStorage.getItem = this.getStorageItem.bind(this);
}
private setStorageItem(key: string, value: string): void {
console.log('setStorageItem', key, value);
this.subject$.next(`${key}: ${value}`);
this.setStorageItemFunc.call(localStorage, key, value);
}
private getStorageItem(key: string): string {
const value = this.getStorageItemFunc.call(localStorage, key);
console.log('getStorageItem', key, value);
return value;
}
如您所见,在截获的函数中,您可以调用@damian-c.
提到的Subject的next()
函数