非 ui 应用程序的 Redux 架构

Redux architecture for a non-ui application

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

我会有多个模块:

  1. Playback Module:封装来自Audio Element的所有回调,并在每次回调后调度一个动作来更新状态。

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

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

问题一: 音频元素有它自己的状态,播放、暂停、搜索、当前时间……而 Redux 状态反映了音频元素的状态。 这是一个好习惯吗?我有点担心在不同的地方有 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;
     }
   }

问题三: 每隔 0.5 秒,Audio 元素会触发一个带有新当前时间的回调。当这个回调被触发时,我派发一个动作来更新状态中的当前时间。 现在,流式处理模块需要了解该更改,以便确定在给定时间需要哪个段,并且需要知道我们是否需要预取未来的段。

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

像那样?:

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

谢谢

让我试着一一解答你的问题:

问题一

假设您正在使用 HTML5 音频组件:redux 状态 augmenting/syncing 与另一个组件(例如您的音频播放器)的状态没有任何问题。不过,在所有情况下,我建议 redux 状态 遵循 音频组件状态(例如应该有延迟)

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

问题二

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

问题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);
    };
}

另一种方法是直接订阅商店状态。这完全取决于您的流媒体模块 structured/instantiated:

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

const store = createStore(...);

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

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

希望对您有所帮助。