Как я могу следить за изменениями в localStorage в Angular2?

Я пытался выяснить, как заставить меню появляться и исчезать на основе входа в предыдущий пост. Но я думаю, что лучший и, возможно, более простой вопрос: как я могу следить за изменениями в localstorage?

Я использую jon web-токены в локальном хранилище для моей аутентификации, мне бы очень хотелось наблюдать за изменением в localStorage, а затем повторно обновить мое представление о новой информации.

Я установил свой localStorage с помощью этого

localStorage.setItem('jwt', my_token);

То, что я хотел бы сделать, это проверить, есть ли у меня токен, если я ничего не делаю, но когда происходит смена события. Мне особенно понравилось бы, если бы я мог наблюдать только за определенным названным событием, например localStorage.getItem('jwt').

Спасибо!

EDIT:

Гюнтер указал мне в правильном направлении, но на всякий случай кто-то все еще довольно смущен этим, вот плункер, показывающий вам, как это сделать. http://plnkr.co/edit/TiUasGdutCsll1nI6USC?p=preview

Ответ 1

Ключевым моментом является использование window.addEventListener("storage",. Хотя библиотека, вероятно, делает это "правильным" способом для angular, вот "облегченная" версия, которую я собрал, используя .bind(this) вместо того, чтобы хулиганить о в угловых внутренних органах.

import { Injectable, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/share'

@Injectable()
export class StorageService implements OnDestroy {
  private onSubject = new Subject<{ key: string, value: any }>();
  public changes = this.onSubject.asObservable().share();

  constructor() {
    this.start();
  }

  ngOnDestroy() {
    this.stop();
  }

  public getStorage() {
    let s = [];
    for (let i = 0; i < localStorage.length; i++) {
      s.push({
        key: localStorage.key(i),
        value: JSON.parse(localStorage.getItem(localStorage.key(i)))
      });
    }
    return s;
  }

  public store(key: string, data: any): void {
    localStorage.setItem(key, JSON.stringify(data));
    // the local application doesn't seem to catch changes to localStorage...
    this.onSubject.next({ key: key, value: data})
  }

  public clear(key) {
    localStorage.removeItem(key);
    // the local application doesn't seem to catch changes to localStorage...
    this.onSubject.next({ key: key, value: null });
  }


  private start(): void {
    window.addEventListener("storage", this.storageEventListener.bind(this));
  }

  private storageEventListener(event: StorageEvent) {
    if (event.storageArea == localStorage) {
      let v;
      try { v = JSON.parse(event.newValue); }
      catch (e) { v = event.newValue; }
      this.onSubject.next({ key: event.key, value: v });
    }
  }

  private stop(): void {
    window.removeEventListener("storage", this.storageEventListener.bind(this));
    this.onSubject.complete();
  }
}

LocalStorageTwoTabs

Ответ 2

Использовать службу и получать доступ только к LocalStorage через эту службу. Затем служба может предоставлять наблюдаемые данные, которые излучают события при внесении изменений, и вы можете подписаться на эти наблюдаемые для получения уведомления.

Ответ 3

Я знаю, что этот пост немного старый, но есть библиотеки, которые могут сделать это за вас. Например, h5webstorage позволит вам обрабатывать localStorage и sessionStorage как обычные объекты, а синхронизация обрабатывается автоматически. Даже изменения в хранилище будут напрямую возвращаться в ваше приложение.

Ответ 4

Обновленная версия fooobar.com/info/385518/... с новым rxjs 6.

import { Injectable, OnDestroy } from '@angular/core';
import { Subject } from "rxjs";
import { share } from 'rxjs/operators';

@Injectable()
export class StorageService implements OnDestroy {
    private onSubject = new Subject<{ key: string, value: any }>();
    public changes = this.onSubject.asObservable().pipe(share());

    constructor() {
        this.start();
    }

    ngOnDestroy() {
        this.stop();
    }

    public getStorage() {
        let s = [];
        for (let i = 0; i < localStorage.length; i++) {
            s.push({
                key: localStorage.key(i),
                value: JSON.parse(localStorage.getItem(localStorage.key(i)))
            });
        }
        return s;
    }

    public store(key: string, data: any): void {
        localStorage.setItem(key, JSON.stringify(data));
        // the local application doesn't seem to catch changes to localStorage...
        this.onSubject.next({key: key, value: data})
    }

    public clear(key) {
        localStorage.removeItem(key);
        // the local application doesn't seem to catch changes to localStorage...
        this.onSubject.next({key: key, value: null});
    }


    private start(): void {
        window.addEventListener("storage", this.storageEventListener.bind(this));
    }

    private storageEventListener(event: StorageEvent) {
        if (event.storageArea == localStorage) {
            let v;
            try {
                v = JSON.parse(event.newValue);
            } catch (e) {
                v = event.newValue;
            }
            this.onSubject.next({key: event.key, value: v});
        }
    }

    private stop(): void {
        window.removeEventListener("storage", this.storageEventListener.bind(this));
        this.onSubject.complete();
    }
}