【问题标题】:BehaviorSubject variable keeps data after logoutBehaviorSubject 变量在注销后保留数据
【发布时间】:2018-04-04 18:20:20
【问题描述】:

我有一个共享服务如下:

data = new BehaviorSubject<any[]>([]);
constructor(userService: UserService){
  if (localStorage.getItem('data') === null) {
    userService.getAllData().subscribe(results =>

      this.data.next(results)
 }
  else {
    this.loadData()
  }
}

loadData() {
  let data = JSON.parse(localStorage.getItem('data');
  this.data.next(data);
}

setData(data) {
  localStorage.setItem('data', JSON.stringify(data))
  this.data.next(data)
}

然后在我的组件上 ngOnInit() 我有:

ngOnInit() {
  this.sharedService.data.subscribe(results =>
    this.allData = results;
  )
}

itemChange() {
  this.allData.slice(index, 5);
  this.sharedService.data.next(this.allData)
}

我有 OnLogout :

   localStorage.removeItem('data')

问题是在第一页重新加载时,服务被调用并且我得到了预期的数据,我进行了更改,然后在我注销后重新登录, 在存储上我没有数据键了,但是 sharedService 没有被再次调用,而是在组件 onInit 上 this.sharedService.data 已经从上次填充。

如何让它每次都调用 sharedService 以便它检查 item('data') 是否存在,就像它在服务构造函数上一样?

【问题讨论】:

  • @ShashankVivek 如果我使用主题,我将无法订阅组件?那我该怎么做呢?因为它确实有效,但是当我注销并重新登录时,onngOnInit 已经填充了来自共享服务的数据。我需要刷新页面,以便它再次调用服务,然后查看并检查它在构造函数上的条件。

标签: angular rxjs


【解决方案1】:

我建议你重组你的服务。这样做。

您不要让订阅者订阅 data-BehaviorSubject 本身,而是订阅一个 getter-method,而不是让您的对象作为 Observable 返回。效果相同,但您现在可以在订阅发生时调用其他私有方法。

import { Observable } from 'rxjs/Observable';

private data = new BehaviorSubject<any[]>([]);

constructor(private userService: UserService){}

getData(): Observable<Array<any>> {

    // called once with/by each subscription    
    this.updateData();

    return this.data.asObservable();
}

现在,对于每个新订阅,您都会调用私有方法 updateData()。此方法将执行您当前在构造函数中执行的检查。但是现在不仅会在服务实例化时进行一次检查,而且会在每次新运行应用程序时进行检查,无论您是关闭浏览器还是简单地注销。

getDataValue(): Array<any> {
    return this.data.getValue();
}

setData(val: Array<any>) {
    localStorage.setItem('data', JSON.stringify(val));
    this.data.next(val);
}


private updateData(): void {
       const storage = localStorage.getItem('data');

       if (storage === null) {

          this.userService.getAllData().subscribe(results => {
             this.data.next(results);
          }

      } else {
          this.data.next(JSON.parse(storage));
      }
}

在你的组件中:

import { Subscription } from 'rxjs/Rx';

private subscription: Subscription;

ngOnInit() {
   this. subscription = this.sharedService.getData().subscribe(results =>
      this.allData = results;
   )
}

ngOnDestroy() {
    if (this.subscription) {
        this.subscription.unsubscribe();
    }
}

应该这样做。

【讨论】:

  • @JennyJ:我希望现在的方法有所帮助。如果是这样,如果您将此答案标记为解决方案并给予支持,我将不胜感激。
  • 绝对!尽管由于某种原因重新登录,但需要一秒钟才能显示正确的数据并重新加载。这绝对有帮助!将其标记为正确:) 非常感谢!
  • 别提了。 :)
  • 快速提问,是不是订阅了两次?因为我显示的 allData 会在我离开和返回时刷新两次。
【解决方案2】:

我猜你必须通过发出初始值来重置你通过 behaviorSubject 发出的值。可能不是完美的答案,但我相信它会起作用。

这背后的原因是自定义 observable 不会自行完成,您需要手动完成。

【讨论】:

    【解决方案3】:

    在您的组件中扩展您的代码。实施订阅,以便在您离开/关闭组件时取消订阅服务:

    import { Subscription } from 'rxjs/Rx';
    
    private subscription: Subscription;
    
    ngOnInit() {
       this. subscription = this.sharedService.data.subscribe(results =>
          this.allData = results;
       )
    }
    
    ngOnDestroy() {
        if (this.subscription) {
            this.subscription.unsubscribe();
        }
    }
    

    PS:如果您不想删除浏览器存储中的对象,请使用 sessionStorage 而不是 localStorage。关闭当前选项卡或整个浏览器后,sessionStorage 中的所有内容都会被删除。

    【讨论】:

    • 又是同样的问题。即使这样,当我注销并重新登录时,旧数据仍然显示,直到我刷新:|
    猜你喜欢
    • 2018-03-17
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    相关资源
    最近更新 更多