在第一次请求完成之前忽略行动的史诗

时间:2017-01-05 15:58:22

标签: rx-java rxjs redux-observable

一位同事和我已经在我们的Android应用程序中添加了一个类似于redux-observable的流程,并且无法弄清楚如何在第一次调用完成之前创建一个停止接收操作的史诗。

最初我认为我们可以使用skipUntil(),但后来意识到skipUntil()的结果被吞下,并且从未传递到链的其余部分。

下面是一些粗略的JS代码,展示了我们希望实现的目标。

  const fetchUserEpic = action$ =>
  action$.ofType(FETCH_USER)
    .skipUntil( /* first request completes */ )
    .mergeMap(action =>
      ajax.getJSON(`/api/users/${action.payload}`)
        .map(response => fetchUserFulfilled(response))
        .takeUntil(action$.ofType(FETCH_USER_CANCELLED))
    );

这几乎就像我需要一个skipMap()运算符,其行为类似于switchMap(),但一次只能尊重一个请求,而忽略所有项目,如果正在进行观察。

感谢您的任何建议。

2 个答案:

答案 0 :(得分:4)

假设您非常确定这是您需要的(通常不是,在执行上一个查询时删除输入意味着结果已过时,switchMap和/或debounce通常是首选的) ,take(1) + repeat应该有效,因为可观察的动作很热。

const fetchUserEpic = action$ =>
  action$.ofType(FETCH_USER)
    .take(1)
    .concatMap(action =>
      ajax.getJSON(`/api/users/${action.payload}`)
        .map(response => fetchUserFulfilled(response))
        .takeUntil(action$.ofType(FETCH_USER_CANCELLED))
    )
    .repeat()

这是一个模拟逻辑的片段。

// simulate action$.ofType(FETCH_USER) every second
const obs1 = Rx.Observable.interval(1000).publish()
obs1.connect()

function getStuff(i) {
  return Rx.Observable.timer(i*1000).mapTo(i)
}

obs1.take(1).concatMap(getStuff).repeat().subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.2/Rx.js"></script>

答案 1 :(得分:3)

你不需要做任何奇特的事情,已经有一个名为exhaustMap的运营商。 exhaustMapconcatMap类似,只是它会默默地删除在前一个请求仍处理时进入的请求。

const fetchUserEpic = action$ =>
  action$.ofType(FETCH_USER)
    .exhaustMap(action =>
      ajax.getJSON(`/api/users/${action.payload}`)
        .map(response => fetchUserFulfilled(response))
        .takeUntil(action$.ofType(FETCH_USER_CANCELLED))
    );