【问题标题】:Instantiate a new Howler Object in Action Creators and dispatch actions on events在 Action Creators 中实例化一个新的 Howler 对象并在事件上调度操作
【发布时间】:2020-03-05 20:30:20
【问题描述】:

所以我正在尝试构建一个 React.js + Redux 音频播放器。 我正在使用 Howler.js 库来处理来自 API 的音频。 我正在从播放器控制按钮和其他组件(例如曲目列表组件)分派操作。 当用户单击 lis 中的轨道时,我正在向 Player Reducer 分派一个轨道对象。我在这里实例化了一个新的嚎叫对象,它可以工作但这里有一些问题:

  • 因为 Howler 从 API 获取数据,所以这是一个异步任务,它是一种反模式。我知道,但在这里我不会触发来自 Howler 的事件,所以它可以工作,但它有点错误。
  • 我不能使用事件触发器,因为它是异步的,而且从 Reducer 分派操作是一种不好的做法。

我想要什么:

  • 在我的 Action Creator 中实例化一个新的 Howler 对象。
  • 使用事件触发器,例如:onload() 或 onloaderror(),调度其他操作来告诉玩家 Howler 已准备好播放歌曲或是否有错误。

代码:

动作创建者

export const PLAYER_INITIALIZE = 'PLAYER_INITIALIZE'
export const initialize = () => {
    return {
        type: PLAYER_INITIALIZE,
    }
}

export const PLAYER_SET_TRACK = 'PLAYER_SET_TRACK'
export const setTrack = (trackId) => {
    return {
        type: PLAYER_SET_TRACK,
    }
}

export const PLAYER_PLAY_TRACK = 'PLAYER_PLAY_TRACK'
export const playTrack = () => {
    return {
        type: PLAYER_PLAY_TRACK,
    }
}

减速器

function PlayerReducer(state = initialPlayerState, action) {
    switch (action.type) {

        case PlayerActions.PLAYER_SET_TRACK:
            if (state.audioObj.state() != 'unloaded')
                state.audioObj.unload();
            return {
                ...state,
                audioObj: new Howl({
                    src: API.API_STREAM_TRACK + action.trackId,
                    html5: true,
                    preload: true,
                    onload: () => {
                        console.log("Track loaded succesfully.");
                    },
                    onloaderror: (id, err) => {
                        console.error("Load Error : " + err);
                    }
                }),
                trackMetadata: action.trackMetadata
            };

        case PlayerActions.PLAYER_PLAY_TRACK:
            state.audioObj.play();
            return {
                ...state,
                isPlaying: true,
            };

      [...]

我的想法是像这样实例化 Howler:

new Howler({
    [ ... some options ],
    onload: () => {
        dispatch({
            type: PLAYER_LOAD_SUCCESS
        });
    },
    onloaderror: () => {
        dispatch({
            type: PLAYER_LOAD_ERROR
        });
    }
});

如何编辑此代码以在 Action Creator 中正确创建新的 Howl 对象并将其传递给我想收听的每个轨道上的播放器?

你能举个例子吗?

谢谢。

【问题讨论】:

    标签: reactjs react-redux action howler.js


    【解决方案1】:

    您可以将redux-thunk 添加到您的应用中,然后能够从单个操作创建者分派多个操作。添加 redux-thunk 后,您的操作可能如下所示:

    export const setTrack = (trackId) => {
      (dispatch, getState) => {
        const { audioObj } = getState();
        if (audioObj != null) {
          audioObj.unload();
        }
    
        dispatch({
          audioObj:  new Howler({
              [ ... some options ],
              onload: () => {
                  dispatch({
                      type: PLAYER_LOAD_SUCCESS
                  });
              },
              onloaderror: () => {
                  dispatch({
                      type: PLAYER_LOAD_ERROR
                  });
              }
          }),
          type: PLAYER_SET_TRACK
      });
    }
    

    您可以通过这种方式将您的其他异步和咆哮工作转移到动作创建者中,并使您的减速器只关心存储信息。

    【讨论】:

    • 感谢您的回答。但是如何从组件中调用异步函数呢?我需要这样做吗:dispatch(setTrack(theTrack))
    • 该函数是同步的,它被称为普通的动作创建者。 dispatch(setTrack(trackId));.
    猜你喜欢
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多