当前位置: 首页 > 知识库问答 >
问题:

本地存储变化的rxjs可观测角度2

廖琨
2023-03-14

我试图创建一个可观察变量,当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 - 导航栏订阅用户服务(获取默认值 loggedIn=false) 步骤 2 - 身份验证组件更新用户服务(设置 loggedIn = true)

我在导航栏中的订阅未更新。我在这里错过了什么。我是否需要像事件发射器一样在UserService的logIn方法中添加一些内容?

共有3个答案

汝楷
2023-03-14

另一种方法是观察< code >存储事件

fromEvent(window, 'storage').subscribe((storageEvent) => {
  //do what you need to do with your storageEvent
})

这意味着您不需要在任何服务层中包装本机API。

宋劲
2023-03-14

我编写了一个 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 的新手,有几个月的经验。欢迎任何改进或建议:-)

潘鸿文
2023-03-14

你想要的是一个主题。在此处查看文档。

举个简单的例子,像这样:

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);
  }
...
 类似资料:
  • 我有一个服务,有一个方法foo。在该方法中,我订阅了一个可观察的(超文本传输协议-客户端)。 我喜欢从foo返回一个布尔值,该值取决于get。这不起作用,因为http.get是asynchrouns-在http.get完成之前调用return。 我怎样才能使这个同步? 编辑 返回可观察的布尔值在这里不是一个选项。这是因为我处理get in foo的响应(此处未显示),但我也需要根据它的返回来执行f

  • 我有一个HTTP请求,希望将结果共享给多个组件。当然,HTTP请求返回一个可观察的。我希望多个组件能够订阅此服务,而不会触发额外的HTTP请求。 我在一个组件中使用实现了这一点,该组件按需发出HTTP请求,并有另一种方法订阅该主题。虽然这是可行的,但似乎有些过分,而且肯定有更好的方法。 主题服务 和一个订户 和第二个订户 从管道链中删除时,会发出多个网络请求。是否有一种更优雅/正确的方式将观察到的

  • 我有一个沙盒,它订阅了一个消息流,我想过滤该流,以查找已发送到或从特定用户使用另一个组件中指定的路由参数接收的消息。 messages.sandbox.ts: messages.detail.container.ts this.matching消息$似乎只包括this.received消息$但是我知道this.sent消息$不是空,因为我可以在我的模板中使用它没有问题。 我是不是遗漏了一些合并观测

  • 在我的应用程序中,我一直在努力进行一些基本的更改检测。我已经这样做了几天了,而且失去了意志!我想知道这里是否有人能给我指出正确的方向。 我有一个和2个列表。一个是给,另一个是给。 此方法连接到数据库以获取对象列表,每个对象都有一个值。现在我想使用这些键去获取每个用户的实际。我什么都试过了,似乎是我唯一能工作的东西。 因此,两者都调用函数,我在模板上使用管道。 我的函数是这样的。 但是,Angula

  • 以下代码未订阅: 但是如果我这样做,它确实订阅: 更新:这个工作太 但当我添加逻辑时,它并没有 我遵循RxJS官方文档:https://rxjs-dev.firebaseapp.com/api/operators/find 我甚至必须在,当我执行时,什么也不会打印出来。我也尝试过使用管道。 对象: 我传递的昵称是将对象与“Devpato”进行比较

  • 嗨,我正在使用angular 7和rxjs async 在我的组件中,我使用ngFor与异步观察者 在我的服务中,我有一个BehaviorSubject,当用户选择一个组时,它会被释放 这是selectedItems$可观察的: 这是可行的,但现在我需要能够更改特定项以响应websocket消息。我有一个websocket连接,用于处理更新项目的消息。有没有一种方法可以使用rxjs的反应式方法来实