在 Action Creators 中实例化一个新的 Howler 对象并在事件上分派操作
Instantiate a new Howler Object in Action Creators and dispatch actions on events
所以我正在尝试构建一个 React.js + Redux 音频播放器。
我正在使用 Howler.js 库来处理来自 API 的音频。
我正在从播放器控制按钮和其他组件(例如曲目列表组件)调度操作。
当用户单击列表中的轨道时,我将轨道对象分派给 Player Reducer。我在这里实例化了一个新的 Howl 对象,它可以工作但是这里有一些问题:
- 因为 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 对象并将其传递给我想收听的每个轨道上的播放器?
你能举个例子吗?
谢谢。
您可以将 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
});
}
您可以通过这种方式将您的其他异步和咆哮工作转移到动作创建者中,并使您的缩减器只关心存储信息。
所以我正在尝试构建一个 React.js + Redux 音频播放器。 我正在使用 Howler.js 库来处理来自 API 的音频。 我正在从播放器控制按钮和其他组件(例如曲目列表组件)调度操作。 当用户单击列表中的轨道时,我将轨道对象分派给 Player Reducer。我在这里实例化了一个新的 Howl 对象,它可以工作但是这里有一些问题:
- 因为 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 对象并将其传递给我想收听的每个轨道上的播放器?
你能举个例子吗?
谢谢。
您可以将 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
});
}
您可以通过这种方式将您的其他异步和咆哮工作转移到动作创建者中,并使您的缩减器只关心存储信息。