redux-observable:一旦另一个被触发至少一次就映射到一个动作

时间:2017-01-23 12:03:11

标签: rxjs redux-observable

我有一个SPA正在从服务器加载一些全局/共享数据(让我们调用此APP_LOAD_OK)和页面特定数据(DASHBOARD_LOAD_OK)。我想显示加载动画,直到调度APP_LOAD_OK和DASHBOARD_LOAD_OK。

现在我在RxJS中表达了这个问题。我需要的是在每个DASHBOARD_LOAD_OK之后触发一个动作,只要有至少一个APP_LOAD_OK。像这样:

action$
  .ofType(DASHBOARD_LOAD_OK)
  .waitUntil(action$.ofType(APP_LOAD_OK).first())
  .mapTo(...)

有人知道,我怎么能在有效的RxJS中表达它?

3 个答案:

答案 0 :(得分:2)

您可以使用withLatestFrom,因为它会等到两个源在发射前至少发射一次。如果您使用DASHBOARD_LOAD_OK作为主要来源:

action$.ofType(DASHBOARD_LOAD_OK)
  .withLatestFrom(action$.ofType(APP_LOAD_OK) /*Optionally*/.take(1))
  .mapTo(/*...*/);

这允许您在DASHBOARD_LOAD_OK多次触发的情况下继续发光。

答案 1 :(得分:1)

我想避免实现一个新的操作符,因为我认为我的RxJS知识不够好,但事实证明它比我想象的要容易。如果有人有更好的解决方案,我会保持开放。您可以在下面找到代码。

Observable.prototype.waitUntil = function(trigger) {
  const source = this;
  let buffer = [];
  let completed = false;

  return Observable.create(observer => {
    trigger.subscribe(
      undefined,
      undefined,
      () => {
        buffer.forEach(data => observer.next(data));
        buffer = undefined;
        completed = true;
      });

    source.subscribe(
      data => {
        if (completed) {
          observer.next(data);
        } else {
          buffer.push(data);
        }
      },
      observer.error.bind(observer),
      observer.complete.bind(observer)
    );
  });
};

答案 2 :(得分:0)

如果你想在第一个APP_LOAD_OK之后收到每个DASHBOARD_LOAD_OK你可以简单地使用skipUntil

action$ .ofType(DASHBOARD_LOAD_OK)
  .skipUntil(action$.ofType(APP_LOAD_OK).Take(1))
  .mapTo(...)

这只会在第一个APP_LOAD_OK之后开始发出DASHBOARD_LOAD_OK动作,之前的所有动作都会被忽略。