Redux thunk:如何等待异步操作的完成

Posted

技术标签:

【中文标题】Redux thunk:如何等待异步操作的完成【英文标题】:Redux thunk: how to await completion of an async action 【发布时间】:2016-10-24 14:57:42 【问题描述】:

由于 redux thunk 异步调用动作创建者返回的函数,我如何在调用动作创建者之后确保 redux 在继续之前实际调度了动作?

我需要在每次向服务器发出 POST 请求之前获取 CSRF 令牌,并且对于这两个过程都有相应的操作。

问题是,如果我连续调用这些动作创建者,POST 动作会由于某种原因在 CSRF 动作被调度之前被调度。我想将这些问题分开,所以我不想合并这些操作。

如何将动作创建者调用代码与调度这些动作的 redux thunk 同步?

【问题讨论】:

【参考方案1】:

您可以将 thunk action creator 作为 Promise,更容易控制异步作业。

export function createXHRAction(xhrType, dispatch, options) 
    // you can customize createXHRAction here with options parameter.

    dispatch( type: xhrType, data:  fetching: true, data: [] );

    return new Promise( (resolve, reject) => 
        fetch(options.url,  ... )
        .then( (response) => 
            // to getting server response, you must use .json() method and this is promise object
            let parseJSONPromise = response.json();

            if(response.status >= 200 && response.status < 300) 
                parseJSONPromise.then( (result) => 
                    dispatch( type: xhrType, data:  fetching: false, data: result.data );
                    resolve(result.data);
                );
                return parseJSONPromise;    // make possible to use then where calling this
            
            else 
                return parseJSONPromise.then( res => 
                    reject( message: res.error.message );
                );
            
        )
        .catch( (error) => 
            // handles common XHR error here
        );
    );

现在您可以像这样轻松创建新的 XHR 操作:

import  createXHRAction  from './actions';

export function getUser(id) 
    return (dispatch) => 
        return createXHRAction('user', dispatch, 
            method: 'get',
            url: `/user/$id`
        );
    ;

现在您可以使用同步等 thunk 操作:

import  dispatch  from './store';
import  getUser  from './action/user';

class SomeComponent extends React.Component 
    ...
    loadData(id) 

        // from here, store's state should be  fetching: true, data: [] 
        dispatch(getUser(id))
        .then( (userData) => 
            // now from here, you can get the value from parameter or you can get it from store or component props if super component passing it by redux provider.
            // store state should be  fetching: false: data [..., ...] 
            // do something with received data
        )
        .catch( (error) => 
        ));

    

【讨论】:

【参考方案2】:

在开始 POST 请求之前,您需要等待 CSRF-token 请求完成。

我认为将所有代码封装到动作创建器中会更好

function postAction(data) 
   fetchToken().then((token) => 
       //you have got token here and can use it for the POST-request.
       doPost(data, token).then(() => 
          //dispatch success action if you need so
       )
   )

【讨论】:

虽然这是一种建设性的解决方法,但在某些情况下,按照发帖人的要求按顺序调度操作会非常有帮助。例如。你正在处理一个复杂的项目,在现有的动作创建器中使用受信任的遗留代码“正常工作”,最好在不修改或重构的情况下调用它们。

以上是关于Redux thunk:如何等待异步操作的完成的主要内容,如果未能解决你的问题,请参考以下文章

Redux 等待异步 thunk 继续进行

Redux等待异步thunk继续前进

如何使用 Redux Thunk 链接动态系列的异步操作?

如何在 Redux 异步 thunk 中使用 AppDispatch 类型?

使用redux-thunk完成异步connect的第二个参数的对象写法。

Redux-thunk 异步操作:使用自定义中间件进行异步操作