【问题标题】:How to create an redux-observable epic that waits for 2 actions before doing anything如何创建一个在做任何事情之前等待 2 个动作的 redux-observable 史诗
【发布时间】:2017-07-11 23:05:17
【问题描述】:

我想创建一个史诗,在工作之前监听一系列明确的动作。

这个史诗在第一次完成后也不需要存在。

我正在想象这样的事情:

function doTheThing(action$) {
  return action$
     // The start of the sequence
    .ofType(FIRST_ACTION)

    // Do nothing until the second action occurs
    .waitForAnotherAction(SECOND_ACTION)

    // the correct actions have been dispatched, do the thing!
    .map(() => ({ type: DO_THE_THING_ACTION }))
    .destroyEpic();
}

redux-observable 可以实现这样的事情吗?

【问题讨论】:

  • 仅供参考,几乎所有 redux 可观察的“我该怎么做”问题实际上只是 RxJS 问题,其中数据流动恰好是动作,但这并不是超级相关。
  • 好的,谢谢你的提醒。添加了rxjs 标签。
  • 您需要访问第一个操作的有效负载吗?第二个怎么样?
  • 不,没有使用任何有效负载。
  • IMO 似乎是一个奇怪的模式。我个人会将这种状态放在 redux 本身中,不需要涉及史诗

标签: javascript redux rxjs redux-observable


【解决方案1】:

正如@jayphelps 在 cmets 中指出的那样,有几个变体取决于您是否需要访问各种事件以及事件是否必须严格排序。所以以下应该都适合:

1) 严格排序不关心事件:

action$
  .ofType(FIRST_ACTION)
  .take(1)
  .concat(action$.ofType(SECOND_ACTION).take(1))
  .mapTo({ type: DO_THE_THING_ACTION })

2) 严格排序确实关心事件

action$
  .ofType(FIRST_ACTION)
  .take(1)
  .concatMap(
    a1 => action$.ofType(SECOND_ACTION).take(1),
    (a1, a2) => ({type: DO_THE_THING_ACTION, a1, a2})
  )

3) 非严格排序(做或不做)关心事件

Observable.forkJoin(
  action$.ofType(FIRST_ACTION).take(1),
  action$.ofType(SECOND_ACTION).take(1),
  // Add this lambda if you *do* care
  (a1, a2) => ({type: DO_THE_THING_ACTION, a1, a2})
)
// Use mapTo if you *don't* care
.mapTo({type: DO_THE_THING_ACTION})

【讨论】:

  • 在这种情况下forkJoin 是否与zip 相同?另外,史诗第一次完成后我们如何摧毁它?
  • 在这种情况下是的,因为如果您使用take(1),您将在第一个事件之后有效地完成流。在其他情况下,它们不会相同,因为forkJoin 只接受每个Observable 的最后一个事件,而zip 尝试匹配每个发射。史诗在每个示例中都被隐含地破坏了,因为它正在完成。
【解决方案2】:

这是使用 redux observables 的样子:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/zip';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/take';


function doTheThing(action$) {
  return Observable
     // waits for all actions listed to complete
    .zip(action$.ofType(FIRST_ACTION).take(1), 
         action$.ofType(SECOND_ACTION).take(1),
     )

    // do the thing
    .map(() => ({ type: DO_THE_THING_ACTION }));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 2021-05-24
    • 1970-01-01
    • 2017-03-22
    相关资源
    最近更新 更多