Skip to content

复杂状态管理:一次前端控制器的设计复盘

发表于:2023-12-07 00:45:00阅读量:

在前端业务中,我们有时会遇到比常规CRUD复杂得多的状态管理场景,它们往往涉及多重状态、复杂规则和高优先级逻辑。本文将复盘一个多音轨、多策略的音频播放控制器的设计过程,探讨如何将复杂的需求拆解为清晰的技术方案。

第一步:需求分析与拆解

项目的核心是实现一个能够同时管理三种不同类型音频播放的控制器。

  1. 背景音乐

    • 播放时机:可按周(如周一、周三)和天内多个时段(如09:00-11:00)进行播放。
    • 播放模式:支持列表循环和随机播放。
    • 结束方式:时段结束时,可选择立即停止或播放完当前歌曲再停止。
  2. 语音插播

    • 播放时机:支持按周或按特定日期播放。
    • 插播方式:支持定时插播、按间隔时间插播(依赖背景音乐)、按间隔歌曲数插播(依赖背景音乐)。
    • 插播行为:可设置单次插播的播放次数;可选择暂停背景音乐,或降低背景音乐音量。
  3. 灾情警报

    • 播放时机:手动触发,随时开启。
    • 优先级:最高。一旦开启,其他所有音频任务必须立即暂停。

第二步:核心模型设计

面对如此复杂交错的规则,关键在于抽象出正确的模型。我们引入了“音轨(Track)”的概念。

系统内存在三条虚拟音轨:背景音乐音轨、语音插播音轨、灾情警报音轨。每条音轨都是一个独立的状态机,拥有自己的核心属性:

  • isPlaying: boolean // 是否正在播放
  • volume: number // 当前音量
  • currentAudio: object // 当前播放的音频信息

通过音轨模型,我们将问题从“如何管理三种音频”简化为“如何管理三条音轨的状态”。而三条音轨之间的交互,则由一个更高层次的“总控制器(Master Controller)”来协调。

总控制器的核心职责就是处理优先级问题:

  • 当“灾情警报”音轨状态变为 isPlaying: true 时,总控制器负责将其他音轨的状态强制设置为暂停。
  • 当“语音插播”需要降低背景音乐音量时,总控制器负责调整“背景音乐”音轨的 volume 属性。

第三步:数据结构与开发规划

模型确立后,下一个关键点是数据标准化。无论背景音乐的周循环配置,还是语音插播的间隔配置,其形式都千差万别。

我们的开发核心,就是编写一个转换器(Transformer),它的作用是:

  1. 获取所有类型的音频配置。
  2. 将这些复杂的、异构的配置数据,全部转换为一套标准的、统一的数据结构。

这个标准数据结构可以是一个“播放事件”数组,每个事件对象都包含明确的播放时间、播放内容、所属音轨、播放行为(播放/暂停/调音)等信息。

javascript
// 伪代码示例
[
  { time: '2023-12-06 09:00:00', track: 'background', action: 'play', audio: {...} },
  { time: '2023-12-06 09:15:00', track: 'interstitial', action: 'play', audio: {...}, behavior: 'duck_background' },
  // ... more events
]