web-dev-qa-db-fra.com

Relire un corps de réponse à partir de la récupération JavaScript

fetch() renvoie une promesse qui (en cas de succès) se résout en un objet Response . Une chose très courante à faire est d'appeler immédiatement Response.json() pour convertir le corps de la réponse en un objet JSON.

Si le corps de la réponse n'est pas un JSON valide, la promesse Response.json() échoue avec une erreur. Le message va dans le sens de:

Jeton X inattendu dans JSON à la position 0

Ce n'est pas très utile lorsque vous essayez de diagnostiquer le problème; idéalement, j'aimerais pouvoir voir le contenu du serveur (qui est souvent un message d'erreur).

Cependant, il semble que vous ne pouvez lire le flux que sur Response.body Une fois (au moins dans Chrome). (Il y a même un indicateur en lecture seule Response.bodyUsed .) Cela s'est déjà produit lorsque Response.json() essaie de convertir le corps en JSON, donc le corps semble être perdu pour toujours en cas d'échec d'analyse JSON.

Existe-t-il un moyen de récupérer le corps de réponse d'origine ... à moins de le lire manuellement (puis de le convertir en JSON) lorsque la promesse fetch d'origine se résout?

15
Craig Walker

Utilisez Response.clone() pour cloner Response

let clone = response.clone();

Vous pouvez également utiliser Response.body.getReader() qui renvoie un ReadableStream pour lire Response en tant que flux, TextDecoder() pour convertir Uint8Array Le flux de données en texte .

25
guest271314

J'ai dû faire face à une API qui a parfois bâclé la réponse JSON - avant de retourner response.json() j'ai fait un clone de l'objet de réponse. en utilisant un bloc catch, je peux déterminer si l'erreur est une SyntaxError et procéder à la correction de l'erreur en utilisant le résultat texte du clone de réponse

un peu comme ça:

var brokenJson = function (url) {
    var responseCopy;
    return fetch(url)
    .then(function (response) {
        responseCopy = response.clone();
        return response.json();
    }).catch(function (err) {
        if (err instanceof SyntaxError) {
            return responseCopy.text()
            .then(function(data) {
                return fixJson(data);
            });
        }
        else {
            throw err;
        }
    }).then(function (json) {
        // do things
    });
};

fixJson est juste une fonction qui corrige les données reçues - dans mon cas, quand elles étaient cassées JSON, elles étaient toujours cassées de la même manière - je pense qu'il y avait un début {ou une fin} supplémentaire - ne me souviens pas

en relisant la question, vous êtes plus susceptible de vouloir enregistrer l'erreur sur la console plutôt que de corriger le json - réécriture facile:

var brokenJson = function (url) {
    var responseCopy;
    return fetch(url)
    .then(function (response) {
        responseCopy = response.clone();
        return response.json();
    }).catch(function (err) {
        if (err instanceof SyntaxError) {
            return responseCopy.text()
            .then(function(text) {
                console.error(text);
                throw err;
            });
        }
        else {
            throw err;
        }
    }).then(function (json) {
        // do things
    });
};
8
Jaromanda X