【问题标题】:Using async await, but can't save returned data in variable使用异步等待,但无法将返回的数据保存在变量中
【发布时间】:2021-05-21 16:42:23
【问题描述】:

我正在尝试将我的令牌保存在 redux reducer 中。 console.log 工作正常,代码正在运行并且令牌显示出来。

当我尝试将结果保存在变量中时 - 异步代码不会运行,并且变量仍未定义。

这是我的减速器代码:

import { generateCSRF } from '../components/System/CSRF';

const csrfReducer = async (state = null, action) => {
    switch(action.type){
        case 'CREATE_CSRF_TOKEN':
            return  (
                async () => {
                    state = await generateCSRF(); // I'm trying to save the returned token in state variable, unsuccesfully.
                }
            );
        default: 
            return (state);
    }
}

export default csrfReducer;

这是我的异步函数:

import { config } from '../../config/global-config';

export const generateCSRF = async () => {
        let fetchGetResponse = await fetch(`${config.api_url}csrf`, {
            method: 'GET',
            headers: {
                Accept: "application/json",
                "Content-Type": "application/json",
            },
            credentials: "include",
            mode: 'cors'
        });
        
        let parsedResponse = await fetchGetResponse.json();
        console.log(parsedResponse.csrfToken) // this line works.
        return parsedResponse.csrfToken;
}

【问题讨论】:

标签: reactjs asynchronous redux async-await


【解决方案1】:

不能有任何副作用的 Redux reducer 代码,参见Reducers Must Not Have Side Effects,它们必须是纯函数。

副作用代码,如API调用,异步代码应放在action creator中,为了支持异步action creator,需要使用redux-thunk中间件。

完整的工作流程是:

  1. 调度 createCsrfToken thunk 异步操作。
  2. 进行 API 调用以获取 csrfToken
  3. 调度CREATE_CSRF_TOKEN同步操作
  4. 在 reducer 中处理 CREATE_CSRF_TOKEN 操作
  5. promise.then() 方法中获取更新状态。

例如

csrfReducer.ts:

const csrfReducer = (state = null, action) => {
  switch (action.type) {
    case 'CREATE_CSRF_TOKEN':
      return action.payload;
    default:
      return state;
  }
};

export default csrfReducer;

actionCreator.ts:

import { generateCSRF } from './api';

export function createCsrfToken() {
  return async (dispatch) => {
    const token = await generateCSRF();
    return dispatch({ type: 'CREATE_CSRF_TOKEN', payload: token });
  };
}

api.ts:

const config = {
  api_url: 'http://localhost:3000/api/',
};

export const generateCSRF = async () => {
  //   let fetchGetResponse = await fetch(`${config.api_url}csrf`, {
  //     method: 'GET',
  //     headers: {
  //       Accept: 'application/json',
  //       'Content-Type': 'application/json',
  //     },
  //     credentials: 'include',
  //     mode: 'cors',
  //   });

  //   let parsedResponse = await fetchGetResponse.json();

  const parsedResponse = {
    csrfToken: 'mocked csrf token',
  };
  return parsedResponse.csrfToken;
};

store.ts:

import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
import csrfReducer from './csrfReducer';

const store = createStore(csrfReducer, applyMiddleware(thunk));
export { store };

main.ts:

import { createCsrfToken } from './actionCreator';
import { store } from './store';

function main() {
  store.dispatch(createCsrfToken() as any).then(() => {
    console.log(store.getState());
  });
}

main();

输出:

mocked csrf token

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-25
    • 2020-03-13
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2021-04-03
    相关资源
    最近更新 更多