Comment gérer les erreurs dans les réponses fetch () avec Redux Thunk?

Je fais des requêtes API en utilisant une récupération isomorphique et j'utilise Redux pour gérer l'état de mon application.

Je veux gérer les erreurs de perte de connexion Internet et les erreurs d'API, en déclenchant des actions Redux.

J'ai le code suivant (travail en cours / mauvais), mais je ne peux pas trouver la manière correcte de déclencher les actions Redux (plutôt que de jeter une erreur et d'arrêter tout):

export function createPost(data = {}) { return dispatch => { dispatch(requestCreatePost(data)) return fetch(API_URL + data.type, { credentials: 'same-origin', method: 'post', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'X-WP-Nonce': API.nonce }, body: JSON.stringify(Object.assign({}, data, {status: 'publish'})) }).catch((err) => { //HANDLE WHEN HTTP ISN'T EVEN WORKING return dispatch => Promise.all([ dispatch({type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message:'Error fetching resources', id: h.uniqueId()}), dispatch({type: PRE_CREATE_API_ENTITY_ERROR, errorType: 'fatal', id: h.uniqueId(), message: 'Entity error before creating'}) ]) }).then((req) => { //HANDLE RESPONSES THAT CONSTITUTE AN ERROR (VIA THEIR HTTP STATUS CODE) console.log(req); if (!req || req.status >= 400) { return dispatch => Promise.all([ dispatch({type: FETCH_RESOURCES_FAIL, errorType: 'warning', message:'Error after fetching resources', id: h.uniqueId()}), dispatch({type: CREATE_API_ENTITY_ERROR, errorType: 'warning', id: h.uniqueId(), message: 'Entity error whilst creating'}) ]) } else { return req.json() } }).then((json) => { var returnData = Object.assign({},json,{ type: data.type }); dispatch(receiveCreatePost(returnData)) }) } } 

Si je désactive incialement la connexion Internet, dans la console JS, lorsque je me connecte via console.log () (comme ci-dessus), il sort ceci: POST http://example.com/post net::ERR_INTERNET_DISCONNECTED(anonymous function) (dispatch) { return Promise.all([dispatch({ type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message: 'Error fetching resources', id: _CBUtils2.default.uniqueId() }), dispatch({ type:… cb_app_scripts.js?ver=1.0.0:27976 Uncaught (in promise) TypeError: req.json is not a function(…)

Pardonnez-moi si cela est tout à fait erroné, mais je ne veux rien faire que déclencher deux actions Redux en cas d'erreur (une erreur générale et une spécifique à l'action que nous avons effectuée lorsque l'erreur s'est produite).

Est ce que j'essaie d'atteindre, même possible?

Il semble que (via ma connexion à la console) la partie 'alors' du script est toujours en cours d'exécution (comme le contenu de ce sont mes fonctions d'envoi "catch").

Je suis confus à propos de plusieurs choses:

  1. Pourquoi utilisez-vous Promise.all autour de l'envoi de deux actions synchrones? Appeler l' dispatch avec quelque chose comme {type: PRE_FETCH_RESOURCES_FAIL, ...} ne renverra pas une promesse, donc Promise.all est inutile. Promise.all() n'est utile que si les actions que vous envoyez sont ellesmêmes écrites comme des créateurs d'actions thunk, ce qui n'est pas le cas ici.
  2. return dispatch => ... n'est nécessaire qu'une fois au tout début des créateurs d'action. Il n'est pas nécessaire de le répéter dans les catch ou les blocs, en fait, en répétant, le code interne ne s'exécute pas du tout. C'est une façon d'injecter l' dispatch dans votre fonction au niveau supérieur, et il est inutile de le répéter.
  3. Si vous mettez, après une catch , il fonctionnera même après qu'une erreur a été détectée. Ce n'est pas le comportement que vous voulez, il n'est pas logique d'exécuter le gestionnaire de succès juste après le gestionnaire d'erreur. Vous voulez qu'ils soient deux chemins de code distincts.
  4. Mentionnage mineur: vous appelez la réponse " req ". Il devrait probablement res .

On dirait que vous avez un mauvais modèle mental de la façon dont Redux Thunk fonctionne et essaie de combiner des parties d'exemples différents jusqu'à ce qu'il clique. L'indentation aléatoire contribue également à ce code étant un peu difficile à comprendre.

Cela va être douloureux à l'avenir, alors je suggère d'obtenir un modèle mental plus complet de ce que Redux Thunk fait, de quoi return dispatch => ... signifie et comment les promesses s'insèrent dans l'image. Je recommanderais cette réponse en tant qu'introduction en profondeur de Redux Thunk .

Si nous corrigeons ces problèmes, votre code devrait ressembler à peu près à ceci:

 export function createPost(data = {}) { return dispatch => { dispatch(requestCreatePost(data)); return fetch(API_URL + data.type, { credentials: 'same-origin', method: 'post', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', 'X-WP-Nonce': API.nonce }, body: JSON.stringify(Object.assign({}, data, {status: 'publish'})) }) // Try to parse the response .then(response => response.json().then(json => ({ status: response.status, json }) )) .then( // Both fetching and parsing succeeded! ({ status, json }) => { if (status >= 400) { // Status looks bad dispatch({type: FETCH_RESOURCES_FAIL, errorType: 'warning', message:'Error after fetching resources', id: h.uniqueId()}), dispatch({type: CREATE_API_ENTITY_ERROR, errorType: 'warning', id: h.uniqueId(), message: 'Entity error whilst creating'}) } else { // Status looks good var returnData = Object.assign({}, json, { type: data.type }); dispatch(receiveCreatePost(returnData)) } }, // Either fetching or parsing failed! err => { dispatch({type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message:'Error fetching resources', id: h.uniqueId()}), dispatch({type: PRE_CREATE_API_ENTITY_ERROR, errorType: 'fatal', id: h.uniqueId(), message: 'Entity error before creating'}) } ); } } 

La solution était simplement (pour les deux instances d'enregistrement des erreurs), remplacer:

 return dispatch => Promise.all([ dispatch({type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message:'Error fetching resources', id: h.uniqueId()}), dispatch({type: PRE_CREATE_API_ENTITY_ERROR, errorType: 'fatal', id: h.uniqueId(), message: 'Entity error before creating'}) ])``` 

Avec:

 return Promise.all([ dispatch({type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message:'Error fetching resources', id: h.uniqueId()}), dispatch({type: PRE_CREATE_API_ENTITY_ERROR, errorType: 'fatal', id: h.uniqueId(), message: 'Entity error before creating'}), Promise.reject(err) ])