Redux重传调度不会返回错误

时间:2018-08-21 07:02:07

标签: redux promise redux-thunk

我正在尝试从调度返回承诺,以便可以在我的react组件中做类似的事情

this.props.dispatch(requestLogin(data))
  .then((res) => {
   Navigate.toHome()
}).catch((err) => {
  this.showErrorMessage()
})

当前,我包装了获取信息以重用我在服务器API上传递的常见内容,并放置一些日志进行调试。我是这样的:

export const query = (path, opts) => {

 // common config and boilerplates here
 // e.g add device id to every api request

 return fetch(opts.url, reqOpts)
    .then((response) => {

       console.log('response received') 

       if (response.ok) {
         return response.json()
       } else
          console.log('response not ok')})
    .then((respData) => {
        if (respData.status === true) {
          console.log('response success') 
          return respData
        } else {
          const errObj = respData
          errObj.server = true
          throw errObj
        }
    }).catch((err) => {
      console.log('error catched')
      if (err.server) {
        throw err
      }
      throw { status: false, errors: { error_code: 'ERR_FATAL', error_msg: 'Something went wrong.' }, err }
    })

然后我的动作创建者是这样的:

export function requestLogin (data) {
  return function (dispatch) {
    const opts = {
      method: 'POST',
      body: data,
    }
    return query(Paths.OP_USR_LOGIN, opts)
        .then((data) => {
           data.TYPE = APP_LOGIN
           dispatch(resultData)
        },
        (data2) => {
          // the thrown error actually returns here
          // this returned value goes to the .then of the dispatch
          return data2
        },
        ).catch((err) => {
          // this is not executed
          return err
        })
  }
}

发生了什么事

this.props.dispatch(requestLogin(data))
          .then((res) => {
         // the error actually goes here
           Navigate.toHome()
        }
        (err) => {
         // not here
        }).catch((err) => {
        // or here
          this.showErrorMessage()
        })

2 个答案:

答案 0 :(得分:4)

首先,重要的是要理解,您给then(onFulfilled, onRejected)提供的第二个参数是onRejected,这是另一个要捕获的语法,因此,因为它是在动作创建者捕获之前编写的,所以您可以查询功能引发错误时,就会出现错误。这就是为什么不执行catch块的原因。 (read about promise's then)。

onRejected中发现错误之后,它会返回一个诺言,这不再是错误(诺言的状态已实现且未被拒绝)。

如果您希望诺言到达陷阱区,则应更改动作创建者:

return query(Paths.OP_USR_LOGIN, opts)
        .then((data) => {
           data.TYPE = APP_LOGIN
           dispatch(resultData)
        },
        (data2) => {
          // the thrown error actually returns here
          // this returned value goes to the .then of the dispatch
          return new Promise((resolve,reject) => {
            reject(data2)
          }
        })

将返回一个承诺,该承诺将被拒绝,因此将被catch块捕获。

此外,您可以更改

return new Promise((resolve,reject) => {
                reject(data2)
              }

throw 'error'

Promise.reject(data2)

如果您需要进一步的说明,请告诉我。

答案 1 :(得分:1)

您做的事情:

query(Paths.OP_USR_LOGIN, opts)
    .then((data) => {
       data.TYPE = APP_LOGIN
       dispatch(resultData)
    },
    (data2) => {
      // the thrown error actually returns here
      // this returned value goes to the .then of the dispatch
      return data2
    })
    .catch((err) => {
      // this is not executed
      return err
    })

实际上,您确实已经捕获了query函数的错误,然后返回了data2。这意味着您要使用data2返回Promise成功(解决)。 catch也会发生同样的事情。

要修复此问题,只需删除(data2) => {}catch块。

query(Paths.OP_USR_LOGIN, opts)
    .then((data) => {
       data.TYPE = APP_LOGIN
       dispatch(resultData)
    })

第二种方式,如果您仍然想对错误进行某些处理,则需要返回Promise.reject

query(Paths.OP_USR_LOGIN, opts)
    .then((data) => {
       data.TYPE = APP_LOGIN
       dispatch(resultData)
    })
    .catch((err) => {
      // you can do something with error, and still return a promise.reject here
      console.log('I found an error here', err)
      return Promise.reject(err)
    })