如何让 redux 派发一个动作并返回一个承诺?
Posted
技术标签:
【中文标题】如何让 redux 派发一个动作并返回一个承诺?【英文标题】:How can I make redux dispatch an action as well as return a promise? 【发布时间】:2017-10-30 07:08:33 【问题描述】:这是我在 songAction.js 中的函数
export function createSong(title, url, token)
axios.defaults.headers.common['Authorization'] = token
return function (dispatch)
axios.post('http://localhost:8080/api/song/create',
title,
link: url
)
.then((response) =>
console.log('the response was', response)
if(response.data.success)
dispatch(type: "CREATE_SONG_FULFILLED", payload: response.data.song)
else
dispatch(type: "CREATE_SONG_REJECTED", payload: response.data)
)
.catch((err) =>
dispatch(type: "CREATE_SONG_REJECTED", payload: err)
)
我希望能够在调度后返回一个承诺,这样我就可以在组件中使用这样的函数 -
createSong(title, url, token)
.then((result) =>
// do stuff with result
)
我知道我可以传入一个回调来使这项工作异步。但我想使用 ES6 的 Promise 特性。我有点困惑如何做到这一点。
【问题讨论】:
function (dispatch)
和 .then((response) =>
都没有返回任何东西,所以这是一个开始的问题
刚从axios返回:return axios.post('http://localhost:8080/api/song/create' ...
【参考方案1】:
我认为使用分派操作的返回值不是很“反应”的方式。
使用Redux Saga,例如here,有一种更好的方法可以解决此类“复杂”情况。
虽然,我过去以这种方式通过调度操作使用返回值:
export const updatePage = (id, batch) =>
return dispatch =>
dispatch(
type: 'UPDATE_PAGE',
payload:
id
)
// Make an API call
return requestUpdatePages(
id, batch
).then(data =>
// When API call is successful
return dispatch(
type: 'UPDATE_PAGE_SUCCESS',
payload:
id,
data
)
)
.catch(error =>
// When API call fails
return dispatch(
type: 'UPDATE_PAGE_FAIL',
payload:
error,
id
,
error: true
)
)
// After dispatch is bound to action creators
// you can use it like this
handleClick(id)
const updatePage = this.props
updatePage(id).then(action =>
if(action.type === 'UPDATE_PAGE_SUCCESS')
console.log('Whee, page has been updated!', action.payload.data)
else
console.error('Something went wrong :-( ', action.payload.error)
)
【讨论】:
【参考方案2】:首先,你需要返回axios
调用。
...
return function (dispatch)
return axios.post('http://localhost:8080/api/song/create',
title,
link: url
)
...
您的 createSong
函数正在返回另一个函数(所以它是一个 curried 函数)。
因此,
createSong(title, url, token)(dispatch)
.then(()=>
// something
)
在我看来非常有效。
【讨论】:
【参考方案3】:如果你想使用完整的 ES6,你应该使用 async/await
语法。这完全消除了处理承诺的需要。
export function createSong (title, url, token)
axios.defaults.headers.common['Authorization'] = token
return async (dispatch) =>
try
const response = await axios.post('http://localhost:8080/api/song/create',
title,
link: url
)
console.log('the response was', response)
if (response.data.success)
dispatch(type: 'CREATE_SONG_FULFILLED', payload: response.data.song)
else
dispatch(type: 'CREATE_SONG_REJECTED', payload: response.data)
catch (err)
dispatch(type: 'CREATE_SONG_REJECTED', payload: err)
createSong
返回的匿名函数用新的async
关键字标记。这意味着匿名函数现在将返回一个隐式 Promise。
async
关键字还允许您在函数体中使用await
,这样您就可以将await
异步调用axios.post
视为同步调用。
另一个优点是您可以重新使用普通的try / catch
块。这些实际上是在解决和拒绝幕后的隐含承诺,但它们以正常方式行事。
因为匿名函数实际上是返回一个 Promise,所以在调用链的上层,无论你在哪里调用 createSong(...)
函数,你也可以使用 async / await
语法 ... 等等。没有更多的回调,也没有更显式的 Promise 处理。
【讨论】:
这可以在不使用async/await
的情况下完成。以上是关于如何让 redux 派发一个动作并返回一个承诺?的主要内容,如果未能解决你的问题,请参考以下文章
另一个组件如何在 react/redux 中监听另一个组件的动作?