【问题标题】:NgRx Get value without subscribingNgRx 无需订阅即可获取价值
【发布时间】:2020-04-05 08:10:12
【问题描述】:

我正在学习一些 ngrx 教程,我想我已经开始思考它了。

我不明白的是如何做一些简单的事情,比如从 Store 获取值:

目标:无需subscribe 即可从商店获得价值。 即:store.myStorePropertystore.getValue(<selector>) 或?

据我了解,从商店中获取价值的唯一方法是执行以下操作:

  private readonly _store: Store<ApplicationState>;
  // ...
  this._store.select(state => state.currentUser).subscribe(user => {
    if (!user) { return; }
    // ...
  });

问题:有没有什么方法可以“立即”从商店获得价值而无需订阅?

我可能只是难以将我的大脑包裹在 selectors 周围,但我有点认为这就是他们的目的。文档中的示例:

import { createSelector } from '@ngrx/store';

export interface FeatureState {
  counter: number;
}

export interface AppState {
  feature: FeatureState;
}

export const selectFeature = (state: AppState) => state.feature;

export const selectFeatureCount = createSelector(
  selectFeature,
  (state: FeatureState) => state.counter
);

在这个例子中,我想我可以调用selectFeature 或将它传递给this._store.select(selectFeature) 来获取实际值,但它返回一个observable(因此希望你订阅它)。

我的主要用例是我想在我的应用程序的整个生命周期中访问当前用户信息。我有一个effect,它正在从服务器获取该信息,并且一切正常。但是,我对如何简单地从store 访问值而不必到处撒.subscribe 感到有些困惑。

是的,我见过this,但这对我没有帮助。

【问题讨论】:

  • 你考虑过使用异步管道吗?
  • 如果异步管道不适合您,您可以在服务的构造函数中订阅一次,将发出的值分配给服务中的公共变量并在您的组件中使用该变量。但您可能会以这种方式访问​​过时的值,通常最好使用响应式方法。
  • 我知道async 管道。这是特定于房屋的 HTML 方面的。我想(立即)从商店获取一个值,以便我可以通过角度服务将该值传递给辅助 api 调用。我不想在我的代码库中到处都是.subscribe
  • 问题是,你的用例是什么?为什么需要在不订阅的情况下从 store 中获取值? ngrx 框架的本质是基于可观察存储(状态),我相信如果您的要求不是这样,那么您应该使用其他一些状态机制。
  • 在他们的 github repo 上阅读了几个(非常)热情(但也很有趣)的线程后,拒绝了对此类功能的功能请求,这是不可能的。该团队似乎非常坚持不实现这种功能,因为它“不是被动的”。花了几天时间才知道你必须订阅所有内容,但现在我明白为什么会这样了。 (github.com/ngrx/store/issues/296) 和 (github.com/ngrx/platform/issues/227)

标签: angular typescript redux rxjs ngrx


【解决方案1】:

你可以像这样使用异步管道

export class MyComponent implements OnInit {
    data$: Observable<any>;

    constructor(private store: Store<ApplicationState>) {}

    ngOnInit() {
        this.data$ = this.store.pipe(select(yourSelector));
    }
}

那么在你看来

<app-data [data]="data$ | async"></app-data>

【讨论】:

  • 这应该是去@mwilson 的方式。当您在其他地方需要该值时,您应该考虑使用 rxjs 运算符将来自 observable 的值与其他值组合。
  • combineLatest 应该很少使用,至少不应该这样使用。您应该使用选择器来组合商店的不同部分
  • 正如问题所述,我想在组件代码中执行此操作。我完全了解async 管道。我想从store 中获取一个值,而不必在我的应用程序中到处撒.subscribe。基本上,我想从 store 中获取一个值,我知道它就在那里,我现在就想要它,而不必订阅 observable。所以,在上面的例子中,我应该可以做console.log(this.data$) 并得到this.data$ 的实际值。不是我必须订阅才能获取数据的 observable。
【解决方案2】:

您如何添加自己的订阅函数并每次都调用它?

  getValue(obj: Observable<any>){
    let value: any;
    obj.subscribe(v => value = v);
    return value;
  }


  showme(){
    console.log(this.getValue(this.user$));     // single value => works
    console.log(this.getValue(this.projects$)); // array => works
  }

请注意,您失去了 observables 的魔力,因此当值发生变化时,它不会更新您的前端等...当您要求该值时,您将获得该时刻的值。

refence to stackblitz demo

您调用选择器的方式似乎是错误的,您应该像这样导入它们:

import * as fromAuth from '../../auth/state/reducers';
import * as fromData from '../../data/state/reducers';

然后你像这样构建你的构造函数:

constructor(private store: Store<fromAuth.State & fromData.State>) {

你的选择可能是这样的,

this.user$ = store.pipe(select(fromAuth.getUser));
let user = this.getValue(store.pipe(select(fromAuth.getUser))); // this would get you the current user value

Check out the ngrx example app 特别是我引用的这个索引页面,以检查选择器。 Check out this sample 关于他们如何使用选择器和导入状态

通常您构建容器和组件。您构建一个容器,负责从存储中获取数据,然后将其与异步管道一起传递给下一个负责显示的容器或组件。使用 ngOnChanges,您可以检测更改并相应地更新前端。

【讨论】:

    【解决方案3】:

    您可以使用状态方法-getValue,获取状态的当前值

    const value: string | undefined = SELECTORS.selectValue(this.state.getValue());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-18
      • 2020-10-07
      • 1970-01-01
      • 2014-03-07
      相关资源
      最近更新 更多