Javascript-Abruf - Fehler beim Ausführen von 'json' bei 'Antwort': Der Body-Stream ist gesperrt


104

Wenn der Anforderungsstatus größer als 400 ist (ich habe 400, 423, 429 Zustände ausprobiert), kann Fetch den zurückgegebenen JSON-Inhalt nicht lesen. Der folgende Fehler wird in der Browserkonsole angezeigt

Nicht erfasst (im Versprechen) TypeError: Fehler beim Ausführen von 'json' bei 'Response': Der Body-Stream ist gesperrt

Ich habe den Inhalt des zurückgegebenen Antwortobjekts wie folgt angezeigt:

Geben Sie hier die Bildbeschreibung ein

Aber ich kann es noch vor ein paar Monaten benutzen.

Meine Frage lautet wie folgt:

  • Ist dies nur das Verhalten des Chrome-Browsers oder die Änderung des Abrufstandards?
  • Gibt es eine Möglichkeit, den Körperinhalt dieser Zustände zu ermitteln?

PS: Meine Browserversion ist Google Chrome 70.0.3538.102 ((正式) (64 位)


Dies bedeutet, dass Sie eine Antwort von der API erhalten, diese jedoch nicht gültig ist. Senden Sie alle erforderlichen Parameter in der Anfrage?
Kiranvj

@kiranvj Ich habe meine Daten überprüft, den gleichen Inhalt, ich habe nur den Statuscode auf 200 geändert, um ihn korrekt zu erhalten.
Luna

1
Ich habe das gleiche Problem, aber mein Status ist 200. Wie haben Sie es schließlich gelöst?
DavSev

@DavSev Für einen bestimmten Statuscode erhalte ich die Rückgabedaten über axios
Luna

1
es passiert auch mit 200.
Schlingel

Antworten:


169

Ich habe diesen Fehler auch festgestellt, aber festgestellt, dass er nicht mit dem Status der Antwort zusammenhängt. Das eigentliche Problem ist, dass Sie ihn nur Response.json()einmal konsumieren können. Wenn Sie ihn mehr als einmal konsumieren, tritt der Fehler auf.

Wie unten:

    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

    }

Die Lösung besteht also darin, zu vermeiden, Response.json()mehr als einmal im thenBlock zu konsumieren .


2
Sie könnten response.clone()vor dem Verzehr.
Balduran

Nett. Ich hatte eine, console.log(r.json()); return r.json();die es kaputt machte.
Mewc

2
Danke, es hat bei mir funktioniert ..... kann jemand dieses seltsame Verhalten erklären?
Sachin

70

Verwenden Sie Response.clone()zum KlonResponse

Beispiel

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

18
Das hat bei mir gut funktioniert, aber versteht jemand, warum das notwendig ist? Ich habe es nachgeschlagen und sehe, dass es manchmal, wenn ein Leser anfängt, das zu lesen Response.body, für diesen Leser gesperrt wird. Aber nach allem, was ich sehen kann (zumindest in meinem Code), hat noch nie etwas mit dem Lesen begonnen ... gibt es eine Erklärung dafür, wie der lesbare Stream automatisch gesperrt werden könnte?
Jenming

5
Ich hatte das gleiche Problem, fand aber heraus, dass ich "res.json ()" in meinem Watch Panel in Chrome Dev Tools hatte, das vor dem Code selbst behoben wurde!
FelipeDrumond

1
warte was? @FelipeDrumond das ist ein verrückter (nicht) Bug!
George Mauer

@GeorgeMauer Nun, wenn wir response.json () nur einmal ausführen können und Ihr Chrome Dev Tools Watch Panel vor Ihrem Code ausgeführt wird, haben Sie eine Ausnahme, da Sie response.json () zweimal ausgeführt haben!
FelipeDrumond

Referenz MDN
Foxiris

7

Antwortmethode wie 'json', 'text' kann einmal aufgerufen werden und wird dann gesperrt. Das veröffentlichte Bild der Antwort zeigt, dass der Körper gesperrt ist. Dies bedeutet, dass Sie bereits das "Dann", "Fang" genannt haben. Um dies zu beheben, können Sie Folgendes versuchen.

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

Oder

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

3

Ich weiß, dass es zu spät ist, aber es kann jemandem helfen:

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

2

Ich habe mich auch daran gehalten. Aber das hat bei mir funktioniert.

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

Viel Glück



1

Ich habe versehentlich ein Antwortobjekt wiederverwendet, ähnlich wie dieses:

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

Diese Linie:

const json2 = await response.json();

Sollte gewesen sein (Antwort2 anstelle der verbrauchten Antwort1):

const json2 = await response2.json();

Die Wiederverwendung der vorherigen Antwort ergab keinen Sinn und es war ein schmutziger Code-Tippfehler ...


1

Das hat bei mir funktioniert

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

0

Wie in der Frage erwähnt, wird Ihr Körper aufgrund des Status des Objekts gesperrt, wenn Sie versuchen, dasselbe Antwortobjekt zu verwenden. Sie können den Wert des Antwortobjekts erfassen und dann versuchen, eine Operation darauf auszuführen (.then ()). Bitte folgen Sie dem Code unten,

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 { ---- })
        }
    } 
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.