如何让redux派遣一个动作并返回一个承诺?

时间:2017-05-29 23:52:00

标签: javascript reactjs asynchronous ecmascript-6 promise

这是我在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})
        })
    }
}

我希望能够在调度后返回一个promise,这样我就可以在组件中使用这样的函数 -

 createSong(title, url, token)
   .then((result) =>{
        // do stuff with result 
     })

我知道我可以通过回调来使这个工作异步..但我想使用承诺的ES6功能。我有点困惑,我怎么能这样做。

3 个答案:

答案 0 :(得分:0)

如果你想要完整的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,这样您就可以awaitaxios.post进行异步调用,因此请将其视为是一个同步电话。

另一个优点是您可以返回使用普通try / catch块。这些实际上是在解决和拒绝幕后的隐含承诺,但它们以正常的方式行事。

因为匿名函数实际上返回了一个Promise,在调用链的上游,无论你调用createSong(...)函数,你也可以使用async / await语法......等等。没有更多的回调,也没有更明确的承诺处理。

答案 1 :(得分:0)

首先,您需要返回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
})

对我来说非常有效。

答案 2 :(得分:0)

我认为它并非“反应”。使用调度操作的返回值的方法。

有一种更好的方法可以解决复杂的问题。这种情况使用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)
    }
  })
}