【问题标题】:How can I make redux dispatch an action as well as return a promise?如何让 redux 派发一个动作并返回一个承诺?
【发布时间】: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' ...

标签: javascript reactjs asynchronous ecmascript-6 promise


【解决方案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的情况下完成。
      猜你喜欢
      • 2021-06-20
      • 2015-11-27
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 2015-06-05
      • 2016-07-18
      相关资源
      最近更新 更多