javascript fetch - Impossibile eseguire "json" su "Response": il flusso del corpo è bloccato


107

Quando lo stato della richiesta è maggiore di 400 (ho provato gli stati 400, 423, 429), il recupero non può leggere il contenuto json restituito. Il seguente errore viene visualizzato nella console del browser

Uncaught (in promessa) TypeError: impossibile eseguire "json" su "Response": il flusso del corpo è bloccato

Ho mostrato il contenuto dell'oggetto risposta restituito come segue:

inserisci qui la descrizione dell'immagine

Ma posso ancora usarlo qualche mese fa.

La mia domanda è la seguente:

  • È solo il comportamento del browser Chrome o le modifiche standard di recupero?
  • C'è un modo per ottenere il contenuto corporeo di questi stati?

PS: la versione del mio browser è Google Chrome 70.0.3538.102 (正式 版本) (64 位)


Ciò significa che stai ricevendo una risposta dall'API, ma non è un json valido, stai inviando tutti i parametri richiesti nella richiesta?
kiranvj

@kiranvj Ho verificato i miei dati, lo stesso contenuto, ho appena cambiato il codice di stato in 200 per ottenerlo correttamente.
Luna

1
Ho lo stesso problema ma il mio stato è 200, come hai risolto alla fine?
DavSev

@DavSev Per un codice di stato specifico, ottengo i dati di ritorno tramite axios
Luna

1
succede anche con 200.
schlingel

Risposte:


175

Ho riscontrato anche questo errore ma ho scoperto che non è correlato allo stato di Risposta, il vero problema è che puoi consumarlo solo Response.json()una volta, se lo stai consumando più di una volta, l'errore si verificherà.

come sotto:

    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

    }

Quindi la soluzione è evitare di consumare Response.json()più di una volta in thenblocco.


5
potresti response.clone()prima di consumarlo.
balduran

Bello. ho avuto un console.log(r.json()); return r.json();che lo ha rotto.
mewc

2
Grazie ha funzionato per me ..... qualcuno può spiegare questo strano comportamento?
Sachin

74

Usa Response.clone()per clonareResponse

esempio

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

19
Questo ha funzionato alla grande per me, ma qualcuno capisce perché è necessario? ho cercato e vedo che a volte una volta che un lettore inizia a leggere Response.body, viene bloccato su quel lettore. Ma da quello che posso vedere (almeno nel mio codice), nulla ha mai iniziato a leggere ... c'è una spiegazione di come lo stream leggibile potrebbe essere bloccato automaticamente?
jenming

5
Ho avuto lo stesso problema, ma ho scoperto di avere "res.json ()" nel pannello dell'orologio in Chrome Dev Tools, che veniva risolto prima del codice stesso!
FelipeDrumond

1
aspetta cosa? @FelipeDrumond è un bug (non) pazzo!
George Mauer

@GeorgeMauer Bene, se possiamo eseguire response.json () solo una volta e il pannello di controllo degli strumenti di sviluppo di Chrome lo esegue prima del codice, avrai un'eccezione perché beh, hai eseguito response.json () due volte!
FelipeDrumond

Riferimento MDN
foxiris

7

Il metodo di risposta come 'json', 'text' può essere chiamato una volta e poi si blocca. L'immagine della risposta pubblicata mostra che il corpo è bloccato. Ciò significa che hai già chiamato "then", "catch". Per risolvere questo problema puoi provare quanto segue.

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

O

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

3

So che è troppo tardi ma può aiutare qualcuno:

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

2

Mi sono anche impegnato in questo. Ma questo ha funzionato per me.

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

in bocca al lupo



1

Stavo accidentalmente riutilizzando un oggetto risposta, qualcosa di simile a questo:

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

Questa linea:

const json2 = await response.json();

Avrebbe dovuto essere (risposta2 invece della risposta1 esaurita):

const json2 = await response2.json();

Riutilizzare la risposta precedente non aveva senso ed era un errore di battitura del codice sporco ...


1

Questo ha funzionato per me

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

0

Come accennato nella domanda, quando stai cercando di utilizzare lo stesso oggetto di risposta, il tuo corpo sta per bloccarsi a causa dello stato dell'oggetto. Quello che puoi fare è acquisire il valore dell'oggetto risposta e quindi provare a eseguire alcune operazioni su di esso (.then ()). Si prega di seguire il codice qui sotto,

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 { ---- })
        }
    } 
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.