我正在尝试将第三方脚本注入页面,并在加载后初始化视频播放器。
我希望能够在任何页面上拥有多个视频播放器,因此我有一些逻辑可以检查脚本是否已经加载,并根据是否进行了不同的操作。
我的“脚本加载”助手看起来像这样:
/**
* 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开发工具中验证这一点),这是预期的。然而,正在发生的事情是史诗只会解决一次承诺(它只会激发地图中的一个动作)。我如何获得史诗为每个承诺决定解雇行动?
我确信它的东西超级简单,我忽略了,但任何帮助都值得赞赏!
答案 0 :(得分:1)
将switchMap
更改为mergeMap
以避免取消:
switchMap与其他展平运算符的主要区别在于取消效果。在每次发射时,前一个内部observable(您提供的函数的结果)被取消,并且新的observable被订阅。您可以通过短语切换到新的可观察对象来记住这一点。
来源:https://www.learnrxjs.io/operators/transformation/switchmap.html