Redux Thunk синхронные действия не синхронны - PullRequest
0 голосов
/ 28 августа 2018

Я использую React / Redux для приложения, которое я создаю, и пытаюсь реализовать действие для выхода пользователя из системы. В моем приложении есть артефакты, которые можно редактировать. Я хочу, чтобы мое приложение сначала сохранило артефакт, а затем вышло из системы, чтобы очистить хранилище. Я реализовал это следующим образом, используя Redux Thunk:

export function logoutUser(artifact) {
  return (dispatch) => {
    dispatch(saveArtifact(artifact))
      .then(() => {
        dispatch(requestLogout());
        return axios.get(`${API_BASE}/auth/logout`)
          .then(() => dispatch(logoutSuccess()))
          .catch(error => dispatch(logoutFailure(error)));
      });
  };
}

Я ожидаю, что это сохранит артефакт и только когда он будет сохранен, выйдите из системы. Мое действие сохранения вызывает другое действие, которое загружает артефакты после их сохранения, но это не должно иметь значения. Он должен вернуть обещание и только затем перейти к выходу пользователя из системы.

Однако это не то, что происходит. По какой-то причине я получаю несколько вызовов для сохранения артефакта (проверено, что они поступают из этой функции), а затем вызовы происходят асинхронно, так что загрузка артефактов является последней, и, таким образом, мое хранилище избыточности не очищается при выходе из системы.

Буду рад, если кто-нибудь сможет дать понять, почему это происходит, и как я могу это исправить.

Дополнительная информация:

Я очищаю хранилище избыточности в моем корневом редукторе следующим образом:

const rootReducer = (state, action) => {
  let newState = state;
  if (action.type === types.LOGOUT_SUCCESS) {
    newState = undefined;
  }

  return appReducer(newState, action);
};

Я сохраняю артефакты следующим образом:

function sendSaveArtifactRequest(artifact) {
  if (artifact._id == null) {
    const artifactWithoutId = _.omit(artifact, ['_id']);
    return axios.post(`${API_BASE}/artifacts`, artifactWithoutId)
      .then(result => result.data);
  }

  return axios.put(`${API_BASE}/artifacts`, artifact).then(() => artifact);
}

export function saveArtifact(artifact) {
  return (dispatch) => {
    dispatch(requestSaveArtifact());

    return sendSaveArtifactRequest(artifact)
      .then(data => dispatch(saveArtifactSuccess(data)))
      .catch(error => dispatch(saveArtifactFailure(error)))
      .then(() => dispatch(loadArtifacts()));
  };
}

Я загружаю артефакты следующим образом:

function sendArtifactsRequest() {
  return new Promise((resolve, reject) => {
    axios.get(`${API_BASE}/artifacts`)
      .then(result => resolve(result.data))
      .catch(error => reject(error));
  });
}

export function loadArtifacts() {
  return (dispatch) => {
    dispatch(requestArtifacts());

    return sendArtifactsRequest()
      .then(data => dispatch(loadArtifactsSuccess(data)))
      .catch(error => dispatch(loadArtifactsFailure(error)));
  };
}

1 Ответ

0 голосов
/ 28 августа 2018

Я обнаружил проблему, в вашем действии saveArtifact несколько цепочек обещаний. Что происходит в вашем случае, после sendSaveArtifactRequest разрешения обещания вы отправляете requestLogout, и после его успеха вы очищаете состояние избыточности. Но с другой стороны, все еще ожидают обещания, которые вы не ожидаете их разрешения в действии logoutUser. Когда вы очищаете избыточное хранилище, ваше ожидающее обещание разрешается и снова обновляется состояние избыточности. Вы можете сделать две вещи здесь:

  • используйте Promise.all().then() при отправке saveArtifact, а затем отправьте действие выхода из системы.
  • Вы можете выйти из системы в действии loadArtifacts, но я не уверен в точном случае использования, возможно, это не соответствует требованиям вашего приложения. но он всегда вызывается при загрузке артефактов.

Самое главное, пожалуйста, интегрируйте Redux DevTools в свое приложение, чтобы вы могли отслеживать последовательность действий, которые отправляются.

в вашем store.js

import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

import rootReducer from './reducers';

const enhancer = compose(
  applyMiddleware(thunk),
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
);

export default createStore(rootReducer, enhancer);

`

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...