Mengambil data dari objek ReadableStream?


135

Bagaimana saya bisa mendapatkan informasi dari suatu ReadableStreamobjek?

Saya menggunakan API Ambil dan saya tidak melihat ini jelas dari dokumentasi.

Tubuh sedang dikembalikan sebagai a ReadableStreamdan saya hanya ingin mengakses properti dalam aliran ini. Di bawah Respons di alat pengembang peramban, saya sepertinya mengatur informasi ini ke dalam properti, dalam bentuk objek 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();
    })


2
@FrancescoPezzella Terima kasih atas tanggapannya. Saya sudah mencoba response.Body.json(), tetapi saya mendapatkan italic TypeError: Tidak dapat membaca properti 'json' dari italic yang tidak terdefinisi . Apakah ini karena properti bodyUsed juga disetel ke false? Namun saya dapat melihat badan ini di bawah tab respons di alat pengembang browser. Ada pesan kesalahan yang ingin saya ambil.
noob

Jadi masalah Anda murni terkait dengan kondisi kesalahan 400? Apa yang terjadi jika Anda mengganti pawang console.log(res.json());? Apakah Anda melihat data yang Anda harapkan?
Ashley 'CptLemming' Wilson

@noob Apakah Anda mencoba membaca respons sebagai streaming jika res.status == 200?
guest271314

Apakah hanya saya atau bahwa dokumentasi polos yang salah? Saya memperbaikinya dengan solusi pada jawaban ini.
Lucio

Jawaban:


177

Untuk mengakses data dari ReadableStreamAnda harus memanggil salah satu metode konversi (dokumen tersedia di sini ).

Sebagai contoh:

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: Jika tipe pengembalian data Anda bukan JSON atau Anda tidak ingin JSON, gunakantext()

Sebagai contoh:

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

Semoga ini bisa membantu membereskan semuanya.


1
Terima kasih atas tanggapannya. Saya telah mencoba ini dan saya masih mendapatkan kesalahan yang sama di mana res.body tidak terdefinisi. Saya dapat mengambil status namun dalam fungsi first () dengan res.status. Tampaknya hanya tubuh yang merupakan objek ReadableStream. Tampaknya memiliki properti terkunci, yang disetel ke true?
noob

Di mana Anda mencoba mengakses res.body(ini bukan bagian dari contoh saya)? Bisakah Anda membagikan beberapa kode sampel dalam pertanyaan awal Anda untuk membuatnya lebih jelas di mana masalah Anda mungkin.
Ashley 'CptLemming' Wilson

1
Saya mencoba mengakses res.body dari respons json yang dikembalikan pada fungsi .then () yang pertama. Saya telah menambahkan sampel ke pertanyaan awal saya untuk kejelasan lebih lanjut. Terima kasih!
noob

1
Luar biasa, menggunakan reaksi dan meminta yang asli, dan bertanya-tanya apa yang harus dilakukan dengan ReadableStream, dan ini berhasil. ++
edencorbin

Hanya sebuah headup, tampaknya seperti no-brainer, tetapi pastikan backend yang Anda pukul benar-benar memberikan JSON yang valid! Jelas tidak berbicara dari pengalaman.
abelito

44

Beberapa orang mungkin menemukan asynccontoh yang bermanfaat:

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

json()mengubah tubuh respons dari objek ReadableStreamke objek json.

The awaitpernyataan harus dibungkus dalam sebuah asyncfungsi, namun Anda dapat menjalankan awaitpernyataan langsung di konsol Chrome (sebagai versi 62).


1
Terkadang jawaban sebenarnya untuk Anda benar-benar adalah # 2 haha, masuk akal mengapa mereka membuat .json () asinkron tetapi tidak segera jelas
Sanchit Batra

29

res.json()mengembalikan janji. Coba ...

res.json().then(body => console.log(body));

3
Saya mencoba ini, dan itu mencetak Janji bukan tubuh.
reectrix

Cobalah untuk membuat .thenpanggilan:fetch(...).then(res => res.json()).then(data => console.log(data))
Óscar Gómez Alcañiz

12

Sedikit terlambat ke pesta tetapi memiliki beberapa masalah dengan mengeluarkan sesuatu yang bermanfaat dari a ReadableStream dihasilkan dari permintaan $ batch Odata menggunakan Sharepoint Framework.

Punya masalah serupa dengan OP, tetapi solusi dalam kasus saya adalah menggunakan metode konversi yang berbeda dari .json(). Dalam kasus saya .text()bekerja seperti pesona. Namun beberapa biola diperlukan untuk mendapatkan JSON yang berguna dari filefile.


2
Terima kasih! Ini berhasil untuk saya. Saya mengirimkan respons http Illuminate dari server Laravel saya dengan sederhana return $data;. Saya akhirnya bisa membaca respons ini di browser denganfetch(...).then(response => response.text()).then(data => console.log(data));
Cameron Hudson

10

Jika Anda hanya ingin respons sebagai teks dan tidak ingin mengubahnya menjadi JSON, gunakan https://developer.mozilla.org/en-US/docs/Web/API/Body/text dan kemudian thenuntuk mendapatkan yang sebenarnya hasil dari janji:

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

atau

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

2

Saya tidak suka chaining thens. Yang kedua kemudian tidak memiliki akses ke status. Seperti yang dinyatakan sebelumnya 'response.json ()' mengembalikan janji. Mengembalikan hasil kemudian dari 'response.json ()' dalam tindakan yang mirip dengan yang kedua itu. Ini memiliki bonus tambahan berada dalam ruang lingkup respons.

return fetch(url, params).then(response => {
    return response.json().then(body => {
        if (response.status === 200) {
            return body
        } else {
            throw body
        }
    })
})

Rantai thenmembantu Anda mengambil nilai akhir yang diselesaikan (the body). Bersarang mereka mencegah Anda mendapatkan bodynilai tanpa panggilan balik atau mekanisme semacam itu. Bayangkan ini: let body = await fetch(...).then(res => res.json()).then(data => data). Ini tidak akan bekerja dengan cara bersarang. Untuk memeriksa response.statusAnda selalu bisa throwpengecualian di dalam yang pertama then, dan menambahkan catchrantai keseluruhan janji.
Óscar Gómez Alcañiz

0

Perhatikan bahwa Anda hanya dapat membaca streaming sekali, jadi dalam beberapa kasus, Anda mungkin perlu mengkloning respons agar dapat membacanya berulang kali:

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))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.