非ui应用程序的Redux架构

时间:2016-07-06 14:59:04

标签: javascript html5 audio redux redux-thunk

我正在开发一个html5音频播放器,我试图找出Redux是否是一个很好的解决方案,即使没有状态(数据)流入的UI。

我将有多个模块:

  1. 播放模块:封装音频元素中的所有回调,并在每次回调后调度操作以更新状态。

  2. 流模块:确定在给定时间需要哪个段的所有逻辑,要预取的段,...

  3. MediaSource模块:媒体源模块是媒体源和源缓冲区的所有操作的包装。

  4. 问题1: 音频元素具有它自己的状态,播放,暂停,搜索,当前时间......,并且Redux状态反映了音频元素的状态。 这是一个好习惯吗?我觉得有点担心在不同的地方有2个状态并且不同步状态......

    问题2: 谁先更新? 让我们想象一下我想暂停我的播放器:

       //Implementation 1:
       function pause() {
         dispatch({type:'PLAYBACK_PAUSED'}).then(()=> {
           this.audio.paused = true; 
         });
       }
    
       // Implementation 2:
       function pause() {
         dispatch({type:'PLAYBACK_PAUSED'});
         this.audio.paused = true;
       }
    
       // Implementation 3:
       function pause() {
         dispatch({type:'PLAYBACK_PAUSED'});
         onPause();
       }
    
       function onPause() {
         const state = getState();
         if  (this.audio.paused != state.paused) {
           this.audio.paused = state.paused;
         }
       }
    

    问题3: 每隔0.5秒,Audio元素会以新的当前时间触发回调。当触发此回调时,我会调度一个操作来更新状态中的当前时间。 现在,Streaming Module需要知道这个变化,以便确定在给定时间需要哪个段,并且需要知道我们是否需要预取未来的段。

    我的流媒体模块应该如何了解状态变化?

    喜欢那个?:

    currentTime = 0;
    ...
    const state = getState();
    if (state.currentTime !== currentTime){
     // Do Something...
     // Do Something Else...
    }
    

    谢谢

1 个答案:

答案 0 :(得分:2)

让我试着逐一解决你的问题:

问题1

假设您正在使用HTML5音频组件:redux状态增强/同步另一个组件(如音频播放器)的状态没有任何问题。但是,在所有情况下,我建议还原状态遵循音频组件状态(例如,如果有延迟)

但是,如果你自己构建了音频组件,也许可以通过直接从中调度事件将其连接到redux生态系统。

问题2

就像我在上一个回答中所说的那样,我总是首先暂停实际组件,然后在组件确认暂停后更新状态。代码方面,这意味着当音频组件完全暂停时触发调度(例如,在onPause回调上)。在状态方面跟踪音频元素而不是期望它遵循我们的状态的原因是因为元素可能不会同步/立即暂停,这可能导致我们的状态不同步。

问题3

当您发送事件以每0.5秒更新一次redux状态时,您可以将另一个事件发送到您的流模块。为此,我建议使用像这样的异步动作创建器:

import StreamingModule from 'your-streaming-module';

export function updateTime (timeInMs) {
    return (dispatch) => {
        dispatch({
            type: YOUR_UPDATE_ACTION
            time: timeInMs
        });

        // pseudo
        StreamingModule.fetchSegment(timeInMs);
    };
}

另一种方法是直接订阅商店状态。这完全取决于您的流模块的结构/实例化方式:

import { createStore } from 'redux';
import StreamingModule from 'your-streaming-module';

const store = createStore(...);

store.subscribe(() => {
    StreamingModule.fetchSegment(store.getState().time.ms);
});

后者可能无法正常工作,除非您在获取段之前将当前时间保存在某处。

希望这有帮助。