Redux observable - 解决多个动作 - 异步

时间:2018-05-15 15:50:47

标签: reactjs redux rxjs redux-observable

我正在尝试将第三方脚本注入页面,并在加载后初始化视频播放器。

我希望能够在任何页面上拥有多个视频播放器,因此我有一些逻辑可以检查脚本是否已经加载,并根据是否进行了不同的操作。

我的“脚本加载”助手看起来像这样:

  /**
   * injectScript - Inject player script into page
   * @param {String} id - script tag id
   * @param {String} src - script src
   * @return {Promise} - script load callback
   */
  injectScript (id, src) {
    return new Promise(resolve => {
      if (!document.getElementById(id)) {
        const script = document.createElement('script');
        script.setAttribute('id', id);
        script.type = 'text/javascript';
        script.src = src;
        document.body.appendChild(script);

        script.onload = () => resolve('script-loaded');
      } else {
        resolve('script-exists');
      }
    });
  }

然后我有一个史诗,它会调用这个助手并根据结果触发一个动作。史诗看起来像这样:

/**
 * loadPlayerScript
 * @param {Object} action$ - action observable
 * @param {Object} store - redux store
 * @param {Object} dependencies - injected dependencies
 * @return {Object} - action observable
 */
export default function loadPlayerScript (action$, store, { scriptLoaderHelper }) {
  return action$.ofType(PLAYER_SCRIPT_LOAD)
    .switchMap(action => Observable.fromPromise(scriptLoaderHelper.injectScript(action.data.id, action.data.script)))
    .map(data => {
      if (data === 'script-loaded') {
        return playerScriptSuccess();
      }

      return playerScriptExists();
    })
    .catch(error => Observable.of(playerScriptFailure(error)));
}

问题:

PLAYER_SCRIPT_LOAD被解雇两次(我可以在Redux开发工具中验证这一点),这是预期的。然而,正在发生的事情是史诗只会解决一次承诺(它只会激发地图中的一个动作)。我如何获得史诗为每个承诺决定解雇行动?

我确信它的东西超级简单,我忽略了,但任何帮助都值得赞赏!

1 个答案:

答案 0 :(得分:1)

switchMap更改为mergeMap以避免取消:

  

switchMap与其他展平运算符的主要区别在于取消效果。在每次发射时,前一个内部observable(您提供的函数的结果)被取消,并且新的observable被订阅。您可以通过短语切换到新的可观察对象来记住这一点。

来源:https://www.learnrxjs.io/operators/transformation/switchmap.html