可观察 - map / concat

时间:2018-05-14 14:41:11

标签: typescript observable ngrx ngrx-store ngrx-effects

我是Observables的新手。我有以下效果。

我希望在派遣SunriseSunsetAction之前调度PositionUpdateAction或PositionFailedAction。

发生的是我将getCurrentPosition()的结果传递到结果变量的最后一个映射中,并调度SunriseSunsetAction。无法调度PositionUpdateAction或PositionFailedAction。

我认为我想在某种程度上使用concat。我一直在努力尝试各种各样的事情。

任何帮助都将不胜感激。

@Effect()
  position$: Observable<Action> = this.actions$.pipe(
    ofType(ActionType.GetPosition),
    mergeMap(() =>
      fromPromise(this.geo.getCurrentPosition()).pipe(
        map(value => new UiActions.PositionUpdateAction(value)),
        catchError((err) => {
          return of(new UiActions.PositionFailedAction(err));
        })
      ).map(result =>
        new UiActions.SunriseSunsetAction(this.sun.calculateSunriseSunsetWindows(result.payload.lat, result.payload.long))
      )
    )
  );

1 个答案:

答案 0 :(得分:1)

我为我理解你的问题提供了一个通用的解决方案。一般情况是您有一些操作,并且您希望使用结果执行另一个操作。最后,您希望发出两者的结果。

在您的特定场景中,第一个操作是一些请求,第二个操作是映射到另一个操作。

解决方案是使用*Map(...)switchMapmergeMap,...)来使用第一个操作的结果来执行第二个操作。您可以使用concat按照您选择的顺序发出两个结果,而不是直接从第二个返回observable。这是一个通用的例子:

&#13;
&#13;
const { of, concat } = rxjs;
const { flatMap } = rxjs.operators;

of(1).pipe(
  flatMap((x) => concat(of(x), of(2)))
).subscribe((x) => { console.log(x); })
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.1.0/rxjs.umd.min.js"></script>
&#13;
&#13;
&#13;

所以你的代码看起来像这样:

@Effect()
position$: Observable<Action> = this.actions$.pipe(
  ofType(ActionType.GetPosition),
  mergeMap(() =>
    fromPromise(this.geo.getCurrentPosition()).pipe(
      map(value => new UiActions.PositionUpdateAction(value)),
      flatMap((x) => concat(
        of(x),
        new UiActions.SunriseSunsetAction(this.sun.calculateSunriseSunsetWindows(result.payload.lat, result.payload.long))
      )),
      catchError((err) => {
        return of(new UiActions.PositionFailedAction(err));
      })
    )
  )
);

由于您正在使用效果,另一种解决方案是设置另一种效果来监听PositionUpdateAction动作。可能会变成意大利面......