3
votes

fetch `then ()` s'exécute même si l'api échoue

Bonjour, j'ai créé un wrapper pour récupérer quelque chose comme ça, j'importe ce wrapper dans les composants mais en cas d'échec catch () de ce wrapper est en cours d'exécution mais dans le composant alors ( ) la fonction exécute n'importe quelle idée !!

    callApi('/someURl', 'GET')
        .then((res) => {
        console.log('this get called even if api fails', res)
    }).catch((err) => {
        //TODO :: error handling at global level
        console.log('Some err', err)
    })
    }

J'appelle cela dans un composant quelque chose comme ça

 import { SERVER_URL } from '../configs/serverConfig';

  export default function callApi(api_url: string, method = 'get', data = null) {


    opts = {
      method: method,
      headers: {
        Authorization: 'Basic VFM0NjA2Omsuc3ZpbTg4',
        Accept: 'application/json',
        'Content-Type': 'application/json'
      }
    };
    if (data) {
      opts.data = JSON.stringify(data);
    }
    return fetchWrapper(api_url, opts);
  }



  function fetchWrapper (api_url: string, opts: any){
    let requestParamObj= {};
    if(opts.method.toLocaleLowerCase() === 'get'){
      requestParamObj = {
        method:opts.method
      }
    }
    else if(opts.method.toLocaleLowerCase() === 'post'){
      requestParamObj = {
        method: opts.method,
        headers: opts.headers,
        body: opts.data
      }
    }


    return (
      fetch(api_url, requestParamObj)
        .then((resp) => resp.json())
        .then(response => {
          return response;
        })
        .catch(error => {
          console.log('request failed', error);
          return error;
        })
    )
  }


1 commentaires

Qu'avez-vous dans votre variable res quand elle échoue, cela peut aider beaucoup de savoir ce qui se passe!


3 Réponses :


2
votes

Ceci est dû au fait que vous détectez l'erreur dans l'encapsuleur et que vous renvoyez une valeur, le consommateur obtiendra donc la valeur renvoyée au lieu de l'erreur.

.then(handleErrors)

si vous remplacez return error par throw error la capture du consommateur sera renvoyée comme prévu.

PS: Fetch API résoudra la promesse même si vous obtenez un statut d'erreur de l'API, elle ne déclenchera que la capture sur les erreurs JavaScript réelles, si vous voulez que la promesse soit rejetée sur les réponses d'erreur du réseau / API également. vous voudrez peut-être faire quelque chose comme ceci

function handleErrors (response) {
  if (!response.ok) {
    console.log('ERROR: ' + response)
    throw Error(response.statusText)
  }
  return response
}

et utiliser

      fetch(api_url, requestParamObj)
        .then((resp) => resp.json())
        .then(response => {
          return response;
        })
        .catch(error => {
          console.log('request failed', error);
          throw error;
        })


0 commentaires

0
votes

L'API fetch rejette la promesse si

une erreur réseau est rencontrée, bien que cela signifie généralement des problèmes d'autorisations ou similaires. MDN

Dans l'exemple suivant, ok sera journalisé:

fetch("http://httpstat.us/500")
    .then(function(response) {
        if (!response.ok) {
            throw Error(response.statusText);
        }
        return response;
    }).then(function(response) {
        console.log("ok");
    }).catch(function(error) {
        console.log(error);
    });

fetch fournit un ok pour vérifier que la réponse est réussie:

fetch("http://httpstat.us/500")
    .then(function() {
        console.log("ok");
    }).catch(function() {
        console.log("error");
    });

Source


0 commentaires

2
votes

Deux choses ne vont pas.

Premièrement, la promesse fetch renvoie uniquement les rejets dans catch si la requête échoue en raison d'une erreur réseau, ou dans un autre mots - la demande ne parvient jamais à votre serveur. Si vous obtenez une réponse, même un HTTP 500, alors la promesse se résout en puis.

Deuxièmement, comme le mentionne l'autre réponse, si vous catch une promesse qui reconvertit la chaîne de promesses en mode de réussite Vous devez lancer ou renvoyer Promise.reject (value) pour remettre la chaîne en mode échec.

Votre wrapper ressemblerait mieux à:

return (
  fetch(api_url, requestParamObj)
    .catch(error => Promise.reject(error)) // Handle network error
    .then(response => {
      if (!response.ok) {
        return Promise.reject(response) // Handle error responses HTTP 4XX, 5XX
      } else {
        return response.json() // Return success response HTTP 2XX, 3XX
      }
    })
)


0 commentaires