Reactjs 在Action Creators中实例化一个新的Howler对象,并对事件分派操作

Reactjs 在Action Creators中实例化一个新的Howler对象,并对事件分派操作,reactjs,react-redux,action,howler.js,Reactjs,React Redux,Action,Howler.js,所以我正在尝试构建一个React.js+Redux音频播放器。 我正在使用Howler.js库处理来自API的音频。 我正在从播放器控制按钮和其他组件(如曲目列表组件)调度操作。 当用户单击lis中的轨迹时,我将轨迹对象分派给播放器。我在这里实例化了一个新的Howl对象,它可以工作,但这里有一些问题: 因为Howler从API获取数据,所以这是一个异步任务,是一个反模式。我知道,但在这里我并没有触发来自Howler的事件,所以它是有效的,但它有点问题 我不能使用事件触发器,因为它是异步的,从R

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

  • 因为Howler从API获取数据,所以这是一个异步任务,是一个反模式。我知道,但在这里我并没有触发来自Howler的事件,所以它是有效的,但它有点问题
  • 我不能使用事件触发器,因为它是异步的,从Reducer中分派操作是一种不好的做法
我想要什么:

  • 在我的动作创建者中实例化一个新的嚎叫对象
  • 使用事件触发器,例如: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,
            };

      [...]
我的想法是像这样描述嚎叫者:

如何编辑此代码以在Action Creator中正确创建新的嚎叫对象,并将其传递给我想要收听的每个曲目上的播放器

你能给我举个例子吗

谢谢。

您可以添加到应用程序中,然后可以从单个动作创建者发送多个动作。添加redux thunk后,您的操作可能如下所示:

export const setTrack=(trackId)=>{
(调度,getState)=>{
const{audioObj}=getState();
如果(audioObj!=null){
audioObj.unload();
}
派遣({
新嚎叫者({
[…一些选择],
加载:()=>{
派遣({
类型:玩家\加载\成功
});
},
onloaderror:()=>{
派遣({
类型:播放器\加载\错误
});
}
}),
类型:播放器\设置\曲目
});
}

您可以通过这种方式将其他异步和Howler工作转移到action Creator中,并使您的reducer只关心存储信息。

谢谢您的回答。但是如何从组件调用异步函数?是否需要执行:
dispatch(setTrack(theTrack))
?该函数是同步的,它的调用与普通操作创建者类似。
调度(setTrack(trackId));
new Howler({
    [ ... some options ],
    onload: () => {
        dispatch({
            type: PLAYER_LOAD_SUCCESS
        });
    },
    onloaderror: () => {
        dispatch({
            type: PLAYER_LOAD_ERROR
        });
    }
});