Récupérer les données d'un objet ReadableStream?

135

Comment puis-je obtenir des informations sur un ReadableStreamobjet?

J'utilise l'API Fetch et je ne vois pas cela clairement dans la documentation.

Le corps est renvoyé en tant que ReadableStreamet je voudrais simplement accéder à une propriété dans ce flux. Sous Réponse dans les outils de développement du navigateur, il semble que ces informations soient organisées en propriétés, sous la forme d'un objet JavaScript.

fetch('http://192.168.5.6:2000/api/car', obj)
    .then((res) => {
        if(res.status == 200) {
            console.log("Success :" + res.statusText);   //works just fine
        }
        else if(res.status == 400) {
            console.log(JSON.stringify(res.body.json());  //res.body is undefined.
        }

        return res.json();
    })
Noob
la source
5
Référence de l'API Body
Francesco Pezzella
2
@FrancescoPezzella Merci pour la réponse. J'ai essayé response.Body.json(), mais j'obtiens de l' italique TypeError: Impossible de lire la propriété 'json' de l' italique non défini . Est-ce parce que la propriété bodyUsed est également définie sur false? Cependant, je peux afficher ce corps sous l'onglet de réponse dans les outils de développement de navigateur. Il y a un message d'erreur que j'aimerais récupérer.
noob
Votre problème est donc purement lié à la condition d'erreur 400? Que se passe-t-il si vous changez le gestionnaire en console.log(res.json());? Voyez-vous les données que vous attendez?
Ashley 'CptLemming' Wilson
@noob Essayez-vous de lire la réponse sous forme de flux si res.status == 200?
invité271314
Est-ce juste moi ou cette documentation est tout simplement fausse? Je l'ai corrigé avec les solutions sur ces réponses.
Lucio

Réponses:

177

Pour accéder aux données à partir d'un, ReadableStreamvous devez appeler l'une des méthodes de conversion (documentation disponible ici ).

Par exemple:

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(function(response) {
    // The response is a Response instance.
    // You parse the data into a useable format using `.json()`
    return response.json();
  }).then(function(data) {
    // `data` is the parsed version of the JSON returned from the above endpoint.
    console.log(data);  // { "userId": 1, "id": 1, "title": "...", "body": "..." }
  });

EDIT: Si votre type de retour de données n'est pas JSON ou si vous ne voulez pas JSON, utiliseztext()

Par exemple:

fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(function(response) {
    return response.text();
  }).then(function(data) {
    console.log(data); // this will be a string
  });

J'espère que cela aidera à clarifier les choses.

Ashley 'CptLemming' Wilson
la source
1
Merci pour la réponse. J'ai essayé ceci et j'obtiens toujours la même erreur où res.body n'est pas défini. Je peux cependant récupérer le statut dans la fonction first then () avec res.status. Il semble que seul le corps soit un objet ReadableStream. Il semble avoir une propriété verrouillée, qui est définie sur true?
noob
Où essayez-vous d'accéder res.body(cela ne fait pas partie de mon exemple)? Pouvez-vous partager un exemple de code dans votre question d'origine pour préciser où se situe votre problème.
Ashley 'CptLemming' Wilson
1
J'ai essayé d'accéder à res.body à partir de la réponse json qui a été renvoyée dans la première fonction .then (). J'ai ajouté un échantillon à ma question initiale pour plus de clarté. Merci!
noob
1
Génial, utiliser react and request native, et se demander quoi faire avec un ReadableStream, et cela a fait l'affaire. ++
edencorbin
Juste un heads-up, cela semble être une évidence, mais assurez-vous que le backend que vous frappez fournit réellement un JSON valide! Certainement pas par expérience.
abelito
45

Certaines personnes peuvent trouver un asyncexemple utile:

var response = await fetch("https://httpbin.org/ip");
var body = await response.json(); // .json() is asynchronous and therefore must be awaited

json()convertit le corps de la réponse de a ReadableStreamen objet json.

Les awaitinstructions doivent être encapsulées dans une asyncfonction, cependant vous pouvez exécuter des awaitinstructions directement dans la console de Chrome (à partir de la version 62).

Noel
la source
1
Parfois, la vraie réponse pour vous est vraiment # 2 haha, il est logique qu'ils rendent .json () asynchrone mais ce n'était pas immédiatement évident
Sanchit Batra
29

res.json()renvoie une promesse. Essayez ...

res.json().then(body => console.log(body));
pinoyyid
la source
3
J'ai essayé ceci, et il a imprimé la promesse au lieu du corps.
reectrix
Essayez d'enchaîner les .thenappels:fetch(...).then(res => res.json()).then(data => console.log(data))
Óscar Gómez Alcañiz
12

Un peu tard à la fête, mais j'ai eu des problèmes pour obtenir quelque chose d'utile d'un ReadableStream j'ai d'une demande de lot Odata $ en utilisant le Framework Sharepoint.

Avait des problèmes similaires à OP, mais la solution dans mon cas était d'utiliser une méthode de conversion différente de celle .json(). Dans mon cas, a .text()fonctionné comme un charme. Quelques manipulations étaient cependant nécessaires pour obtenir du JSON utile à partir du fichier texte.

Dan Mehlqvist
la source
2
Je vous remercie! Cela a fonctionné pour moi. J'envoie une réponse http Illuminate depuis mon serveur Laravel avec un simple return $data;. J'ai enfin pu lire cette réponse dans le navigateur avecfetch(...).then(response => response.text()).then(data => console.log(data));
Cameron Hudson
10

Si vous voulez juste la réponse sous forme de texte et que vous ne voulez pas la convertir en JSON, utilisez https://developer.mozilla.org/en-US/docs/Web/API/Body/text et ensuite thenpour obtenir le réel résultat de la promesse:

fetch('city-market.md')
  .then(function(response) {
    response.text().then((s) => console.log(s));
  });

ou

fetch('city-market.md')
  .then(function(response) {
    return response.text();
  })
  .then(function(myText) {
    console.log(myText);
  });
AlexChaffee
la source
2

Je n'aime pas l'enchaînement alors. Le second n'a alors pas accès au statut. Comme indiqué précédemment, 'response.json ()' renvoie une promesse. Renvoyer le résultat then de 'response.json ()' dans un acte similaire à un second alors. Il a l'avantage supplémentaire d'être dans le champ de la réponse.

return fetch(url, params).then(response => {
    return response.json().then(body => {
        if (response.status === 200) {
            return body
        } else {
            throw body
        }
    })
})
Mardok
la source
Le chaînage thenvous aide à récupérer la valeur résolue finale (lebody ). Les imbriquer vous empêche de pouvoir obtenir la bodyvaleur sans rappel ni mécanisme de ce type. Imaginez ceci: let body = await fetch(...).then(res => res.json()).then(data => data). Cela ne fonctionnerait pas de manière imbriquée. Pour vérifier, response.statusvous pouvez toujours throwune exception à l'intérieur du premier thenet ajouter un catchà toute la chaîne de promesse.
Óscar Gómez Alcañiz
0

Notez que vous ne pouvez lire un flux qu'une seule fois, donc dans certains cas, vous devrez peut-être cloner la réponse afin de la lire à plusieurs reprises:

fetch('example.json')
  .then(res=>res.clone().json())
  .then( json => console.log(json))

fetch('url_that_returns_text')
  .then(res=>res.clone().text())
  .then( text => console.log(text))
Chris Halcrow
la source