tìm nạp javascript - Không thực thi được 'json' trên 'Phản hồi': luồng nội dung bị khóa


107

Khi trạng thái yêu cầu lớn hơn 400 (tôi đã thử các trạng thái 400, 423, 429), tìm nạp không thể đọc nội dung json trả về. Lỗi sau được hiển thị trong bảng điều khiển của trình duyệt

Uncaught (trong lời hứa) LoạiError: Không thực hiện được 'json' trên 'Phản hồi': luồng nội dung bị khóa

Tôi đã hiển thị nội dung của đối tượng phản hồi được trả về như sau:

nhập mô tả hình ảnh ở đây

Nhưng tôi vẫn có thể sử dụng nó cách đây vài tháng.

Câu hỏi của tôi như sau:

  • Đây chỉ là hành vi của trình duyệt Chrome hay các thay đổi tiêu chuẩn tìm nạp?
  • Có cách nào để có được nội dung cơ thể của các trạng thái này?

Tái bút: Phiên bản trình duyệt của tôi là Google Chrome 70.0.3538.102 (正式 版本) (64 位)


Điều này có nghĩa là bạn đang nhận được phản hồi từ api, nhưng nó không phải là json hợp lệ, bạn có đang gửi tất cả các tham số bắt buộc trong yêu cầu không?
kiranvj

@kiranvj Mình đã xác minh dữ liệu của mình, nội dung tương tự, mình chỉ đổi mã trạng thái thành 200 để lấy chính xác.
Luna

1
Tôi có cùng một vấn đề nhưng trạng thái của tôi là 200, làm thế nào bạn giải quyết nó cuối cùng?
DavSev 21/12/18

@DavSev Đối với mã trạng thái cụ thể, tôi nhận được dữ liệu trả về thông qua axios
Luna

1
nó cũng xảy ra với 200.
schlingel

Câu trả lời:


175

Tôi cũng gặp lỗi này nhưng phát hiện ra nó không liên quan đến trạng thái Đáp ứng, vấn đề thực sự là bạn chỉ có thể sử dụng Response.json()một lần, nếu bạn sử dụng nhiều hơn một lần, lỗi sẽ xảy ra.

như dưới đây:

    fetch('http://localhost:3000/movies').then(response =>{
    console.log(response);
    if(response.ok){
         console.log(response.json()); //first consume it in console.log
        return response.json(); //then consume it again, the error happens

    }

Vì vậy, giải pháp là tránh tiêu thụ Response.json()nhiều hơn một lần trong thenkhối.


5
bạn có thể response.clone()trước khi tiêu thụ nó.
Balduran

Đẹp. tôi đã có một console.log(r.json()); return r.json();cái mà đã phá vỡ nó.
mewc

2
Cảm ơn nó đã làm việc cho tôi ..... bất cứ ai có thể giải thích hành vi kỳ lạ này?
Sachin

74

Sử dụng Response.clone()để nhân bảnResponse

thí dụ

fetch('yourfile.json').then(res=>res.clone().json())

19
Điều này rất hiệu quả đối với tôi, nhưng có ai hiểu tại sao điều này lại cần thiết không? tôi đã tra cứu nó, và tôi thấy rằng đôi khi một người đọc bắt đầu đọc Response.body, nó sẽ bị khóa đối với người đọc đó. Nhưng từ những gì tôi có thể thấy (ít nhất là trong mã của tôi), không có gì đã từng bắt đầu đọc ... có lời giải thích về cách luồng có thể đọc được tự động bị khóa không?
jenming

5
Tôi gặp sự cố tương tự nhưng phát hiện ra rằng tôi có "res.json ()" trong bảng đồng hồ của mình trong các công cụ dành cho nhà phát triển chrome, vấn đề này đang được giải quyết trước khi có mã!
FelipeDrumond

1
đợi đã, gì? @FelipeDrumond đó là một lỗi (không phải) điên rồ!
George Mauer

@GeorgeMauer Chà, nếu chúng tôi chỉ có thể chạy response.json () một lần và bảng điều khiển công cụ dành cho nhà phát triển chrome của bạn chạy điều đó trước khi mã của bạn, bạn sẽ có một ngoại lệ vì tốt, bạn đã chạy response.json () hai lần!
FelipeDrumond

Tham khảo MDN
foxiris

7

Metode phản hồi như 'json', 'text' có thể được gọi một lần và sau đó nó khóa. Hình ảnh phản ứng được đăng tải cho thấy cơ thể bị khóa. Điều này có nghĩa là bạn đã gọi 'then', 'bắt'. Để khôi phục điều này, bạn có thể thử các cách sau.

fetch(url)
    .then(response=> response.body.json())
    .then(myJson=> console.log(myJson))

Hoặc là

fetch(url)
    .catch(response=> response.body.json())
    .catch(myJson=> console.log(myJson))

3

Tôi biết đã quá muộn nhưng nó có thể giúp ai đó:

let response = await fetch(targetUrl);
let data = await response.json();

2

Tôi cũng mắc kẹt vào điều này. Nhưng điều này đã làm việc cho tôi.

fetch(YOUR_URL)
.then(res => {
  try {
    if (res.ok) {
      return res.json()
    } else {
      throw new Error(res)
    }
  }
  catch (err) {
    console.log(err.message)
    return WHATEVER_YOU_WANT_TO_RETURN
  }
})
.then (resJson => {
  return resJson.data
})
.catch(err => console.log(err))

chúc may mắn



1

Tôi đã vô tình sử dụng lại một đối tượng phản hồi, một thứ tương tự như thế này:

const response = await new ReleasePresetStore().findAll();
const json = await response.json();
this.setState({ releasePresets: json });

const response2 = await new ReleasePresetStore().findActive();
const json2 = await response.json();
this.setState({ active: json2 });
console.log(json2);

Đường thẳng này:

const json2 = await response.json();

Đáng lẽ ra (response2 thay vì response1 đã sử dụng hết):

const json2 = await response2.json();

Sử dụng lại phản hồi trước đó không có ý nghĩa gì và đó là lỗi đánh máy mã bẩn ...


1

Điều này đã làm việc cho tôi

response.json().then(data => {
  // use data
})

0

Như đã đề cập trong câu hỏi khi bạn đang cố gắng sử dụng cùng một đối tượng phản hồi, cơ thể của bạn sắp bị khóa do trạng thái của đối tượng. Những gì bạn có thể làm là nắm bắt giá trị của đối tượng phản hồi và sau đó cố gắng thực hiện một số thao tác trên nó (.then ()). Vui lòng làm theo mã bên dưới,

fetch('someurl').then(respose) => {
    let somedata = response.json(); // as you will capture the json response, body will not be locked anymore. 
    somedata.then(data) => {
        {
             error handling (if (data.err) { ---- })
        }
        {
             operations (else { ---- })
        }
    } 
}
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.