Lấy dữ liệu từ một đối tượng ReadableStream?


135

Làm thế nào tôi có thể nhận được thông tin từ một ReadableStreamđối tượng?

Tôi đang sử dụng API tìm nạp và tôi không thấy điều này rõ ràng trong tài liệu.

Cơ thể đang được trả lại dưới dạng ReadableStreamvà tôi chỉ muốn truy cập vào một tài sản trong luồng này. Trong phần Phản hồi trong các công cụ phát triển trình duyệt, tôi dường như sắp xếp thông tin này thành các thuộc tính, dưới dạng một đối tượng 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 Cảm ơn bạn đã phản hồi. Tôi đã thử response.Body.json(), nhưng tôi nhận được kiểu chữ nghiêngError: Không thể đọc thuộc tính 'json' của chữ in nghiêng không xác định . Đây có phải là do thuộc tính bodyUsed cũng được đặt thành false? Tuy nhiên tôi có thể xem phần thân này dưới tab phản hồi trong các công cụ phát triển trình duyệt. Có một thông báo lỗi mà tôi muốn lấy.
noob

Vì vậy, vấn đề của bạn hoàn toàn liên quan đến điều kiện lỗi 400? Điều gì xảy ra nếu bạn thay đổi xử lý thành console.log(res.json());? Bạn có thấy dữ liệu bạn đang mong đợi không?
Ashley 'CptLemming' Wilson

@noob Bạn đang cố đọc phản hồi dưới dạng luồng nếu res.status == 200?
khách271314

Là nó chỉ cho tôi hay rằng tài liệu là đồng bằng sai? Tôi đã sửa nó với các giải pháp về câu trả lời này mặc dù.
Lucio

Câu trả lời:


177

Để truy cập dữ liệu từ một ReadableStreambạn cần gọi một trong các phương thức chuyển đổi (tài liệu có sẵn ở đây ).

Ví dụ:

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: Nếu kiểu trả về dữ liệu của bạn không phải là JSON hoặc bạn không muốn JSON thì hãy sử dụngtext()

Ví dụ:

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

Hy vọng điều này sẽ giúp mọi thứ rõ ràng lên.


1
Cảm ơn vì sự trả lời. Tôi đã thử điều này và vẫn nhận được cùng một lỗi trong đó res.body không được xác định. Tôi có thể truy xuất trạng thái tuy nhiên trong hàm then () đầu tiên với res.status. Dường như chỉ có cơ thể là một đối tượng ReadableStream. Nó dường như có một tài sản bị khóa, được đặt thành đúng?
noob

Bạn đang cố gắng truy cập ở đâu res.body(đây không phải là một phần trong ví dụ của tôi)? Bạn có thể chia sẻ một số mã mẫu trong câu hỏi ban đầu của bạn để làm cho nó rõ ràng hơn về vấn đề của bạn.
Ashley 'CptLemming' Wilson

1
Tôi đã thử truy cập res.body từ phản hồi json được trả về trong hàm .then () đầu tiên. Tôi đã thêm một mẫu vào câu hỏi ban đầu của tôi để rõ ràng hơn. Cảm ơn!
noob

1
Tuyệt vời, sử dụng phản ứng và yêu cầu bản địa, và tự hỏi những gì trên thế giới sẽ làm với ReadableStream, và điều này đã làm được điều đó. ++
edencorbin

Chỉ là một headup, có vẻ như không có trí tuệ, nhưng hãy chắc chắn rằng phần phụ trợ bạn đang thực sự cung cấp JSON hợp lệ! Chắc chắn không nói từ kinh nghiệm.
abelito

44

Một số người có thể tìm thấy một asyncví dụ hữu ích:

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

json()chuyển đổi cơ thể của phản ứng từ một ReadableStreamđối tượng json.

Các awaitcâu lệnh phải được gói trong một asyncchức năng, tuy nhiên bạn có thể chạy các awaitcâu lệnh trực tiếp trong bảng điều khiển của Chrome (kể từ phiên bản 62).


1
Đôi khi, câu trả lời thực sự cho bạn thực sự là # 2 haha, điều đó có lý do tại sao họ tạo ra .json () không đồng bộ nhưng điều đó không rõ ràng ngay lập tức
Sanchit Batra

29

res.json()trả lại một lời hứa. Thử ...

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

3
Tôi đã thử điều này, và nó in ra Lời hứa thay vì cơ thể.
reectrix

Hãy thử xâu chuỗi các .thencuộc gọi:fetch(...).then(res => res.json()).then(data => console.log(data))
Óscar Gómez Alcañiz

12

Đến bữa tiệc muộn một chút nhưng có một số vấn đề với việc lấy thứ gì đó hữu ích từ ReadableStream sản phẩm được tạo ra từ yêu cầu lô Odata $ sử dụng Sharepoint Framework.

Có vấn đề tương tự như OP, nhưng giải pháp trong trường hợp của tôi là sử dụng một phương thức chuyển đổi khác .json(). Trong trường hợp của tôi .text()làm việc như một lá bùa. Tuy nhiên, một số vấn đề cần thiết là có được một số JSON hữu ích từ tệp văn bản.


2
Cảm ơn bạn! Điều này làm việc cho tôi. Tôi đang gửi một phản hồi http của Illuminate từ máy chủ Laravel của tôi một cách đơn giản return $data;. Cuối cùng tôi đã có thể đọc phản hồi này trong trình duyệt vớifetch(...).then(response => response.text()).then(data => console.log(data));
Cameron Hudson

10

Nếu bạn chỉ muốn phản hồi dưới dạng văn bản và không muốn chuyển đổi nó thành JSON, hãy sử dụng https://developer.mozilla.org/en-US/docs/Web/API/Body/text và sau thenđó để có được thực tế kết quả của lời hứa:

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

hoặc là

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

2

Tôi không thích dây xích. Thứ hai sau đó không có quyền truy cập vào trạng thái. Như đã nêu trước 'answer.json ()' trả lại một lời hứa. Trả về kết quả sau đó của 'answer.json ()' trong một hành vi tương tự như một giây sau đó. Nó có thêm phần thưởng là trong phạm vi của phản ứng.

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

Chuỗi thengiúp bạn lấy giá trị được giải quyết cuối cùng (the body). Lồng chúng ngăn bạn có thể nhận được bodygiá trị mà không cần gọi lại hoặc một số cơ chế sắp xếp. Hãy tưởng tượng điều này : let body = await fetch(...).then(res => res.json()).then(data => data). Điều này sẽ không hoạt động theo cách lồng nhau. Để kiểm tra, response.statusbạn luôn có thể có throwmột ngoại lệ trong lần đầu tiên thenvà thêm một catchchuỗi vào toàn bộ chuỗi hứa hẹn.
Óscar Gómez Alcañiz

0

Lưu ý rằng bạn chỉ có thể đọc một luồng một lần, vì vậy trong một số trường hợp, bạn có thể cần sao chép phản hồi để đọc lại nhiều lần:

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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.