6

可能是我是一个菜鸟,还没有完全理解这些东西应该如何工作,但我有一个 redux-observable 的史诗,我想用它来创建一个承诺,它将调度一个动作并等待一个在解决之前采取不同的行动。我已经通过将动作映射到它来工作,'__IGNORE__'但我真的不想这样做。有没有办法让一个史诗般的处理一个动作,但不传递任何其他东西?

这是我的代码:

export const waitFor = (type, action) => new Promise((resolve, reject) => {
   const waitForResult = action$ => action$.ofType(type).do(() => resolve()).mapTo({type: "___IGNORE___"});
   registerEpic(waitForResult);

   action();
 });
4

1 回答 1

17

.ignoreElements()您可以使用RxJS 运算符从可观察链中丢弃任何 next'd 值

action$.ofType(type)
  .do(() => resolve())
  .ignoreElements();

另一种方法(没有更多对错)是创建一个只订阅的匿名 Observable。

const waitForResultEpic = action$ => new Observable(observer =>
  action$.ofType(type)
    .subscribe(() => resolve())
);

这隐式返回了我们创建的订阅,因此它也附加到我们的 rootEpic 的生命周期中。因为我们从不调用observer.next(),所以这个史诗从不发出任何值;就像ignoreElements()


尽管您没有问,但您最终可能会注意到您的史诗将永远运行,侦听与type变量匹配的传入动作。这可能不是您想要的,如果您想匹配一次然后完成。

您可以使用.take(1)运算符来完成此操作。

const waitForResult = action$ =>
  action$.ofType(type)
    .take(1)
    .do(() => resolve())
    .ignoreElements();

或者

const waitForResult = action$ => new Observable(observer =>
  action$.ofType(type)
    .take(1)
    .subscribe({
      next: () => resolve(),
      error: err => observer.error(err),
      complete: () => observer.complete()
    })
);

这只会在应用程序的整个生命周期内匹配一次——一旦收到就不会再匹配了。

于 2016-11-03T18:23:02.273 回答