Angulr / Rxjs同步运行存储(ngrx)调用

时间:2019-07-26 11:56:13

标签: angular async-await rxjs ngrx

从商店(ngrx)检索2个对象后,我需要执行一个操作,因此,在执行我的操作之前,我需要两个调用都已响应,就像这样:

SELECT c.CustomerName
FROM customer c INNER JOIN
     sales s
     ON c.id = s.CustomerId
GROUP BY c.id, c.CustomerName
HAVING SUM(s.SalesPrice) > 100;  

我试图在rxjs中寻找带有switchMap,mergeMap等的解决方案,但无法将其应用于我的需求。我想我找到了一种执行异步/等待的解决方案,但是我不确定这是否是一个好习惯,您能告诉我吗?这是异步/等待代码段:

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);

感谢您的帮助。

3 个答案:

答案 0 :(得分:3)

重构为以下内容:

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));

答案 1 :(得分:1)

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());

答案 2 :(得分:0)

或者,您可以在效果中使用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))),
      ),
    ),
  );