2017-02-22 3 views
0

J'utilise le Fetch API pour charger du JSON. Par conséquent, j'utilise .json() sur le flux de réponse et également l'argument optionnel deuxième fonction (onRejected) dans .then(), qui a un seul argument, le motif de rejet.Rejected Fetch Promise: accès au texte de réponse

Si quelque chose ne va pas (comme la réponse n'est pas un JSON valide), je veux accéder au texte de la réponse brute pour avoir un journal des erreurs significatif ou pour traiter la réponse inattendue.

Tenir compte cet extrait simplifié:

fetch('api.php') 
.then(
    response => { return response.json(); } 
) 
.then(
    json => { /* useful fulfillment value, a JSON object */ }, 
    reason => { /* string message only */ } 
); 

Si l'API répond par autre chose que valide JSON, il rejettera la raison suivante:

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

Bien que ce soit un message d'erreur parfaitement clair , il manque un vidage de ce qui en fait causé l'erreur.

J'ai envisagé d'utiliser .text() puis d'essayer d'analyser le JSON moi-même, mais cela contreviendrait quelque peu à l'objectif de .json().

Existe-t-il un moyen raisonnable d'accéder au texte de la réponse si la lecture de flux est rejetée?

Répondre

0

Vous pouvez vérifier le type de contenu:

var contentType = response.headers.get("content-type"); 
    if(contentType && contentType.indexOf("application/json") !== -1) { 
     response => { return response.json(); } 
    } 
    else{ 
     response => { return response.text(); } 
    } 

Si vous voulez obtenir la réponse dans le rappel de rejet que vous pouvez faire quelque chose comme ça

response => { 
      var text = ''; 
      try{ 
       text= response.json(); 
      } 
      catch (e if e instanceof SyntaxError) { 
      text = response.text(); 
      } 
      return text; 
    } 
+1

Ce serait une manière simple et sûre de s'assurer que la réponse arrive au traitement, mais il faudrait vérifier si l'argument * était * JSON. Je pourrais utiliser '.text()' tout de suite.La question était de savoir s'il y avait un moyen d'accéder à la réponse dans le rappel de rejet. – dakab

+1

Qu'en est-il un try..catch comme ci-dessus? – cjds

+1

L'avez vous essayé? Il appelle toujours la fonction de rejet, probablement parce qu'aucune réaffectation n'a lieu après la lecture du flux de réponse. – dakab

0

Disons que cela est méchant mais pourrait résoudre le problème:

let res; 
fetch('api.php') 
.then(
    response => { res = response; return response.json(); } 
) 
.then(
    json => { /* useful fulfillment value, a JSON object */ }, 
    reason => { /* use res variable */ } 
); 
0

Si la réponse est sûre d'avoir un corps alors lisez le texte en utilisant la méthode response.text() (comme indiqué dans les autres réponses ou ailleurs: MDN, Google Web) puis analysez-le vous-même avant ou après toute condition ou vérification supplémentaire (est-ce JSON? vérifiez puis utilisez JSON.parse).

L'utilisation du corps n'est pas une technique efficace pour traiter généralement les erreurs. Que se passe-t-il dans les cas où l'API n'inclut pas de corps ou est-elle mal formée ou la requête échoue-t-elle entièrement? Au lieu de cela, regardez le response.statusText (par exemple 'Non trouvé.'), response.status (par exemple 404) et d'autres en-têtes. Ou dans les cas où le fetch échoue la réponse sera un objet Error avec un error.message et error.stack. Si vous possédez l'API et que vous avez besoin d'une messagerie plus sophistiquée/prévisible, pensez à ajouter des en-têtes personnalisés tels que 'message-spécial' et récupérez-le avec quelque chose comme if(response.headers) response.headers.get('special-message').

Seulement travailler avec le corps une fois que ces autres scénarios ne sont pas un problème pour avoir un peu plus de prévisibilité. Les en-têtes ci-dessus sont également disponibles avant la fin du streaming pour simplifier et améliorer la réactivité et la gestion des réponses.