Redux thunk dispatch 不返回错误

Posted

技术标签:

【中文标题】Redux thunk dispatch 不返回错误【英文标题】:Redux thunk dispatch does not return error 【发布时间】:2019-01-27 07:44:30 【问题描述】:

我正在尝试从调度返回一个承诺,以便我可以在我的反应组件中做这样的事情

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

目前我包装了我的 fetch 以重用我在服务器 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()
        )

【问题讨论】:

【参考方案1】:

首先,重要的是要了解您提供的第二个参数then(onFulfilled, onRejected),即onRejected,是另一种要捕获的语法,因此因为它是在动作创建器中的捕获之前编写的,所以当查询时您会到达那里函数抛出错误。这就是为什么不执行 catch 块的原因。 (read about promise's then)。

当您在onRejected 中发现错误后,它会返回一个不再是错误的承诺(承诺的状态已完成且未被拒绝)。

如果你想让 promise 到达 catch 块,你应该改变你的 action creator:

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)
          
        )

这将返回一个被拒绝的promise,因此它将被catch块捕获。

另外,你可以改变

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

throw 'error'

Promise.reject(data2)

如果您需要任何进一步的解释,请告诉我。

【讨论】:

【参考方案2】:

当你这样做时:

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)
    )

【讨论】:

以上是关于Redux thunk dispatch 不返回错误的主要内容,如果未能解决你的问题,请参考以下文章

Redux-thunk - dispatch 不是一个函数

Redux thunk:从分派的动作返回承诺

使用 redux-thunk 和直接调用 dispatch() 有啥区别

Redux-Thunk Chaining Actions,得到一个“dispatch(...)然后不是函数错误

将接口传递给`dispatch<ShowSnackbar>()` 时,Redux-thunk ThunkDispatch 类型失败

Redux Thunk, Sequelize (Bluebird) - 向动作创建者“链”返回承诺