web-dev-qa-db-fra.com

Annulation de l'action asynchrone précédente à l'aide de redux-thunk

Je construis une application React/Redux en utilisant le middleware redux-thunk pour créer et gérer des requêtes Ajax. J'ai un thunk particulier qui est renvoyé assez souvent, et je voudrais annuler toutes les demandes Ajax commencées précédemment avant d'en lancer une nouvelle. Est-ce possible?

11
Steven Musumeche

Une solution serait de marquer ces demandes comme annulées en leur attribuant un identifiant aléatoire et en vérifiant son statut avant de traiter le résultat.

Pour ce faire, attribuez un identifiant aléatoire à cet appel lors de votre premier envoi (à l'intérieur du thunk) et vérifiez-le dans le réducteur avant de traiter le résultat.

const actionId = Math.random();
dispatch({type: AJAX_LOAD_CONST, id:actionId })

Lorsque vous souhaitez annuler toute l'utilisation de la demande 

dispatch({type:HANDLE_AJAX_RESPONSE, id:actionId, results: json })

Lorsque vous voulez gérer les résultats, n'oubliez pas d'envoyer l'id que vous avez

et dans le réducteur ont quelque chose comme ça:

function reducer(state = initialState, action) {
  switch (action.type) {
    case actions.AJAX_LOAD_CONST:
      return Object.assign({}, state, { ajax: state.ajax.concat(action.id) });
    case actions.CANCEL_ALL_AJAX:
      return Object.assign({}, state, { ajax: [] });
    case actions.HANDLE_AJAX_RESPONSE:
      if (state.ajax.includes(action.id) {
        //return state reduced with action.results here
      }
      return state;
  }
}

Si vous utilisez XMLHttpRequest ou l'un de ses wrappers (JQuery?), Vous pouvez également stocker les demandes elles-mêmes et appeler request.abort (). Si vous utilisez la nouvelle API Fetch, vous ne disposez pas de ce luxe, car les promesses manquent de ce comportement.

11
mrras

Si vous utilisez jquery ajax, vous pouvez faire en sorte que le créateur de votre action retourne la promesse. Elle sera retournée par la fonction dispatch et il sera alors possible de l'abandonner. Voici un exemple :

Créateur d'action

function doSomething() {
  return (dispatch) => {
    return $.ajax(...).done(...).fail(...);
  }
}

Votre composant

  componentDidMount(){
    this.previousPromise = this.props.dispatch(doSomething());
  }

  somefnct() {
    this.previousPromise.abort();
  }
3
Mohamed Ramrami

J'ai récemment été confronté au même problème, dans lequel je devais annuler des actions de redux asynchrones en attente ou obsolètes. Je l'ai résolu en créant un middleware d'annulation des actions redux.

Dans redux, nous avons les concepts de middlewares. Ainsi, lorsque vous envoyez la demande, celle-ci passe par une liste de middlewares. Une fois que l'API a répondu, sa réponse passe par un certain nombre de middlewares avant qu'elle n'atteigne le magasin redux et éventuellement votre interface utilisateur.

Supposons maintenant que nous avons écrit un middleware d'annulation. La requête de l'API passera par ce middleware lors de son lancement et la réponse de l'API passera également par ce middleware lorsque l'API répond en retour.

Chaque requête api dans redux est associée à une action, chaque action ayant un type et une charge utile.

Ecrivez un middleware qui, chaque fois qu'une requête API est effectuée, stocke le type d'action associé. Parallèlement à cela, il stocke un drapeau qui indique si cette action doit être ignorée. Si une action de type similaire est à nouveau déclenchée, activez la case à cocher true qui annule cette action. Lorsque la réponse de l'API vient pour l'action précédente puisque l'indicateur de rejet de cette demande de l'API a été défini sur true, envoyez null comme réponse du middleware.

Regardez ce blog pour des informations détaillées sur cette approche. 

https://tech.treebo.com/redux-middlewares-an-approach-to-cancel-redux-actions-7e08b51b83ce

0
Sumit Gupta