【问题标题】:Angular/Rxjs run store (ngrx) calls synchronouslyAngular/Rxjs 同步运行存储(ngrx)调用
【发布时间】:2019-12-04 18:30:51
【问题描述】:

在从我的商店 (ngrx) 检索到 2 个对象后,我需要执行一个操作,因此,在执行我的操作之前,我需要两个调用都做出响应,如下所示:

const item1$: Observable<Item> = this._store$.select(
  ItemStoreSelectors.selectItemById(this.id1)
);

const item2$: Observable<Item> = this._store$.select(
  ItemStoreSelectors.selectItemById(this.id2)
);

let item1: Item;
item1$.pipe(take(1)).subscribe((item: Item) => {
  item1 = item;
});

let item2: Item;
item2$.pipe(take(1)).subscribe((item: Item) => {
  item2 = item;
});

// here, items might not have been initialized
doSomething(item1, item2);

我尝试在 rxjs 中使用 switchMap、mergeMap 等寻找解决方案,但无法将其应用于我的需求。我想我找到了执行 async/await 的解决方案,但我不确定这是一个好习惯。

感谢您的帮助。

【问题讨论】:

标签: angular async-await rxjs ngrx


【解决方案1】:

重构为以下代码:

import { forkJoin } from 'rxjs';

const item1$: Observable<Item> = this._store$.select(
  ItemStoreSelectors.selectItemById(this.id1)
);

const item2$: Observable<Item> = this._store$.select(
  ItemStoreSelectors.selectItemById(this.id2)
);

forkJoin([item1$.pipe(take(1)), item2$.pipe(take(1))])
   .subscribe(([item1,item2])=>doSomething(item1,item2));
  

【讨论】:

  • 谢谢它看起来很棒,所以如果我理解得很好,订阅只会在两个项目都被触发时触发?
  • 正确,forkJoin 创建了一个 observable,它在所有源完成后发出其源的最后一个值。
【解决方案2】:

combineLatest 每次可观察到的火灾都会触发,如果这是你想要的,试试这个:

item1$: Observable<Item> = this._store$.select(
  ItemStoreSelectors.selectItemById(this.id1)
);

item2$: Observable<Item> = this._store$.select(
  ItemStoreSelectors.selectItemById(this.id2)
);

result$: Observable<any> = combineLatest(this.item1$, this.item2$, this.doSomething());

【讨论】:

  • 也谢谢你,我将作为@Jota 研究 combineLatest 和 forkJoin 之间的区别。托莱多回答了,但我认为它不能完全满足我的需求,因为我需要一个管道(take(1))
【解决方案3】:

或者,您可以在效果中使用 withLatestFrom。像这样的

@Effect()
  myAction$ = this.actions$.pipe(
    ofType<MyAction>(MyActionTypes.MyAction),
    withLatestFrom(this.store.select(mySelector)),
    withLatestFrom(this.store.select(myOtherSelector)),
    exhaustMap(([[action, item1], item2]) =>
      this.myService.myRequest(/*...*/)
      .pipe(
        map(myResult => new GetResultSuccess(myResult)),
        catchError(error => of(new GetResultFailure(error))),
      ),
    ),
  );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 2018-10-12
    • 2019-12-24
    • 2023-03-18
    • 2020-02-16
    • 2016-12-30
    • 2017-06-07
    相关资源
    最近更新 更多