pobieranie javascript - nie udało się wykonać „json” w „Response”: strumień treści jest zablokowany


112

Gdy stan żądania jest większy niż 400 (próbowałem 400, 423, 429 stanów), funkcja pobierania nie może odczytać zwróconej zawartości json. Następujący błąd jest wyświetlany w konsoli przeglądarki

Uncatcht (in promise) TypeError: Failed to execute „json” on „Response”: body stream jest zablokowane

Zawartość zwróconego obiektu odpowiedzi pokazałem następująco:

wprowadź opis obrazu tutaj

Ale mogę go używać jeszcze kilka miesięcy temu.

Moje pytanie brzmi następująco:

  • Czy to tylko zachowanie przeglądarki Chrome, czy standardowe zmiany pobierania?
  • Czy istnieje sposób, aby uzyskać zawartość ciała w tych stanach?

PS: Wersja mojej przeglądarki to Google Chrome 70.0.3538.102 (正式 版本) (64 位)


Oznacza to, że otrzymujesz odpowiedź z interfejsu API, ale nie jest to prawidłowy plik json. Czy wysyłasz wszystkie wymagane parametry w żądaniu?
kiranvj

@kiranvj Zweryfikowałem swoje dane, tę samą treść, właśnie zmieniłem kod statusu na 200, aby uzyskać poprawny.
Luna

1
Mam ten sam problem, ale mój status to 200, jak ostatecznie go rozwiązałeś?
DavSev,

@DavSev Dla konkretnego kodu statusu otrzymuję dane zwrotne przez axios
Luna

1
dzieje się tak również z 200.
schlingel

Odpowiedzi:


183

Spotkałem też ten błąd, ale okazało się, że nie jest to związane ze stanem odpowiedzi, prawdziwy problem polega na tym, że możesz skonsumować tylko Response.json()raz, jeśli zużyjesz go więcej niż raz, błąd się wydarzy.

jak poniżej:

    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

    }

Więc rozwiązaniem jest unikanie spożywania Response.json()więcej niż raz w thenbloku.


6
możesz response.clone()przed spożyciem.
balduran

Ładny. miałem, console.log(r.json()); return r.json();który go zepsuł.
mewc

2
Dzięki, dla mnie zadziałało… Czy ktoś może wyjaśnić to dziwne zachowanie?
Sachin

Dzięki, stary, dla mnie to zadziałało idealnie
Ronny Perez

75

Służy Response.clone()do klonowaniaResponse

przykład

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

19
To działało świetnie dla mnie, ale czy ktoś rozumie, dlaczego jest to konieczne? Sprawdziłem to i widzę, że czasami, gdy czytelnik zacznie czytać Response.body, zostaje on zablokowany. Ale z tego, co widzę (przynajmniej w moim kodzie), nic nie zaczęło się czytać ... czy istnieje wyjaśnienie, w jaki sposób czytelny strumień może zostać automatycznie zablokowany?
jenming

6
Miałem ten sam problem, ale dowiedziałem się, że mam "res.json ()" w moim panelu zegarka w chrome dev tools, który był rozwiązywany przed samym kodem!
FelipeDrumond

1
czekaj, co? @FelipeDrumond to szalony (nie) błąd!
George Mauer

@GeorgeMauer Cóż, jeśli możemy uruchomić response.json () tylko raz, a panel zegarka chrome dev tools uruchomi to przed twoim kodem, będziesz miał wyjątek, ponieważ cóż, uruchomiłeś response.json () dwa razy!
FelipeDrumond

Odniesienie MDN
foxiris

8

Metodę odpowiedzi, taką jak „json”, „tekst” można wywołać raz, a następnie blokuje. Opublikowany obraz odpowiedzi pokazuje, że treść jest zablokowana. Oznacza to, że już zadzwoniłeś do „wtedy”, „złap”. Aby rozwiązać ten problem, możesz spróbować wykonać następujące czynności.

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

Lub

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

4

Wiem, że jest za późno, ale może komuś pomóc:

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

Dokładnie to, czego potrzebowałem, aby rozwiązać tę sprawę za pomocą składni async / await, dziękuję!
ttemple

2

Ja też się w to utknąłem. Ale to zadziałało dla mnie.

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))

powodzenia



1

Przypadkowo ponownie użyłem obiektu odpowiedzi, coś podobnego do tego:

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);

Ta linia:

const json2 = await response.json();

Powinno być (odpowiedź2 zamiast zużytej odpowiedzi1):

const json2 = await response2.json();

Ponowne użycie poprzedniej odpowiedzi nie miało sensu i była to brudna literówka ...



0

Jak wspomniano w pytaniu, gdy próbujesz użyć tego samego obiektu odpowiedzi, twoje ciało zostanie zablokowane z powodu stanu obiektu. To, co możesz zrobić, to przechwycić wartość obiektu odpowiedzi, a następnie spróbować wykonać na nim jakąś operację (.then ()). Postępuj zgodnie z poniższym kodem,

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 { ---- })
        }
    } 
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.