【问题标题】:Is it possible to return early in a Redux Action是否可以在 Redux Action 中提前返回
【发布时间】:2017-10-31 01:29:28
【问题描述】:

问题
我觉得这是一个范围界定问题。我无法在 catch 块中返回。它总是返回成功。虽然 if 语句适用于失败部分(我使用 console.log 对其进行了调试)。

背景信息
有一个使用 laravel 的后端 API。在这段代码中,我登录 API 以使用 react-redux 获取 JWT 令牌。将来调用 API 需要此令牌。代码运行良好,并在实际成功时收到令牌,但我无法在失败时提前返回。

export function requestApiToken(username, password){    
    const url = ROOT_URL + 'user/login';
    const request = axios.post(url, {
        email: username,
        password: password,
        headers: {
            'Content-Type': 'application/json',
            'X-Requested-With': 'XMLHttpRequest'
        }
    })
    .catch(function (error) {
        //somehow it always returns an error
        //currently 500=succes (will fix that later in api to 200)

        if(error.response.status == 500){
            console.log('succes')
            console.log(error.response.data);
        }else{
            console.log('error')
            console.log(error.response.data);
            return{
                type: FETCH_API_TOKEN_FAILURE,
                token: null,
                message: 'Please enter a valid e-mail and username for the API and try again'
            }
        }
    });

    return{
        type: FETCH_API_TOKEN_SUCCES,
        token: request, //should be error.response.data
        message: 'Succesfull login'
    }
}

编辑作为对评论部分的回应。
这是服务器返回的内容:

如果块成功(调试)

如果块失败(调试)

目前代码总是在代码块中返回 FETCH_API_TOKEN_SUCCES

正如答案中所建议的那样,我通过使用 redux-thunk 作为我的中间件而不是 redux-promise 来让它工作

在 index.js 中添加

import thunk from 'redux-thunk';
const createStoreWithmiddleware = applyMiddleware(thunk)(createStore);

在requestApiToken方法中

return(dispatch) => {
        request.then(function (response) {
            dispatch({
                type: FETCH_API_TOKEN_SUCCESS,
                token: response.data.token,
                message: 'Successfull login'
            })
        });
        request.catch(function (error) {
            if(error.response.status == 422){
                dispatch({
                        type: FETCH_API_TOKEN_FAILURE,
                        token: null,
                        message: 'Please enter a valid e-mail and username for the DiabetesAPI and try again'
                })
            }
        });

        dispatch({
            type: FETCH_API_TOKEN_PENDING,
            token: null,
            message: 'Pending API Token request'
        });
    }

【问题讨论】:

  • 尝试删除 if 语句只是为了调试目的
  • @AmrAly 我更新了我的问题,感谢您的帮助
  • 我相信你会需要使用redux-thunk中间件。
  • Redux-thunk 解决了这个问题,感谢@AmrAly

标签: reactjs react-redux axios


【解决方案1】:

呃,你的代码有很多问题。慢慢来,了解您尝试使用的每个概念是如何工作的,这可能是个好主意。

动作创建者是一个返回描述动作的普通对象的函数。

Axios 是一个库,可让您向服务器发出请求。 Axios.post() 将返回一个 Promise,它允许您使用 then() 和 catch() 方法处理请求的结果。这些方法采用回调函数,并且您已经正确地为您的 catch() 调用提供了一个。问题是回调中的 return 语句从回调返回,而不是从动作创建者返回。您不能在操作创建者中进行异步 API 调用,然后从成功或失败回调中返回操作。

另一个问题是您在 Axios.post() 调用之后返回了成功操作。这意味着动作创建者将在调用后立即返回成功动作,而无需等待它返回响应。

如果您想在您的动作创建者中进行 API 调用,请查看 redux-thunk,这是 Redux 中间件,可让您从动作创建者返回承诺,这些承诺可以在解决或拒绝时派发自己的动作。

【讨论】:

  • Redux thunk 修复了答案,感谢您的反馈
【解决方案2】:

如果失败,您的应用程序流程如下所示:

  1. 在解决post 承诺之前返回FETCH_API_TOKEN_SUCCESS
  2. 网络调用失败,promise 是 rejectedcatch 块被执行
  3. JS 引擎处理 catch 块语句并返回具有 FETCH_API_TOKEN_FAILURE 操作类型的新承诺

我建议您对网络调用使用三态方法,例如PENDING, SUCCESS and FAILURE。在这种情况下,您可以显示加载程序并准确知道您的网络调用何时完成。

export function requestApiToken(username, password) {
    const url = ROOT_URL + 'user/login';
    const request = axios.post(url, {
        email: username,
        password: password,
        headers: {
            'Content-Type': 'application/json',
            'X-Requested-With': 'XMLHttpRequest'
        }
    })
    .then(function (response) {
        return {
            type: FETCH_API_TOKEN_SUCCESS,
            token: response.token,
            message: 'Successfull login'
        }
    })
    .catch(function (error) {
        return {
            type: FETCH_API_TOKEN_FAILURE,
            token: null,
            message: getErrorMessage(error.response.status)
        }
    });

    return Promise.resolve({
        type: FETCH_API_TOKEN_PENDING,
        token: null,
        message: 'Loading'
    });
}

function getErrorMessage(statusCode) {
    if (statusCode == 422) { 
        return 'Please enter a valid e-mail and username for the API and try again';
    } else {
        return 'Error has occurred';
    }
}

请注意,您需要在 reducer 中通过 then 解析动作创建者的值,因为返回值将是 Promise

正如其他人所注意到的,您将需要 redux-thunk 中间件来处理 reducer 中的承诺。

附:您正在返回带有 token: request 字段的 FETCH_API_TOKEN_SUCCESS 操作。在这种情况下,request 是一个承诺,我假设您在进一步的代码中正确处理了这个问题。

P.S.S 您的 catch 块很可能不会返回任何内容,因为 catch 中的 return 语句将被包装到 promise 中,您需要通过 thencatch 解决它

【讨论】:

  • 感谢您的帮助。不幸的是,服务器以某种方式成功返回 500 错误。我将此添加到我原来的问题中。它没有进入 .then 块,但它总是在 catch 块中(只是错误状态取决于)。此外,您的答案中没有发送令牌失败部分,也没有以某种方式发送。有什么想法吗?
  • 您的意思是我的方法或原始方法中的 500 错误? 500 错误不会被调度,因为 catch 块只在状态码为 422 时返回一些值,这也不是一个好方法。无论如何,您应该返回一些操作,但可能会指定错误消息。如果需要,我可以更新我的答案
  • 成功时服务器响应 500。失败时响应 422。不知何故 .then 从未在 console.log 中尝试过
  • 因为500不是成功状态,应该在catch块中处理
  • then 仅当状态码在 200 和 299 之间时才会执行
猜你喜欢
  • 2016-03-12
  • 2023-03-23
  • 2018-08-12
  • 2012-02-01
  • 2023-03-24
  • 1970-01-01
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多