Я пытаюсь внедрить сторонний скрипт на страницу и после его загрузки инициализировать видеоплеер.
Я хочу иметь несколько видеопроигрывателей на любой странице, поэтому у меня есть логика, чтобы проверить, загружен ли уже скрипт, и запускать различные действия в зависимости от того, загружен он или нет.
Мой помощник по загрузке скрипта выглядит так:
/**
* 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), это ожидаемо. Но что происходит, так это то, что эпос выполняет обещание только один раз (и запускает только одно из действий на карте). Как мне заставить эпос запускать действия для каждого разрешения обещания?
Я уверен, что это что-то очень простое, на что я не обращаю внимания, но любая помощь приветствуется!





Измените switchMap на mergeMap, чтобы избежать отмены:
The main difference between switchMap and other flattening operators is the cancelling effect. On each emission the previous inner observable (the result of the function you supplied) is cancelled and the new observable is subscribed. You can remember this by the phrase switch to a new observable.
источник: https://www.learnrxjs.io/operators/transformation/switchmap.html