recuperación de javascript: no se pudo ejecutar 'json' en 'Respuesta': el flujo del cuerpo está bloqueado

107

Cuando el estado de la solicitud es superior a 400 (he intentado 400, 423, 429 estados), fetch no puede leer el contenido json devuelto. El siguiente error se muestra en la consola del navegador

No detectado (en promesa) TypeError: No se pudo ejecutar 'json' en 'Respuesta': la transmisión del cuerpo está bloqueada

Mostré el contenido del objeto de respuesta devuelto de la siguiente manera:

ingrese la descripción de la imagen aquí

Pero todavía puedo usarlo hace unos meses.

Mi pregunta es la siguiente:

  • ¿Es esto solo el comportamiento del navegador Chrome o los cambios estándar de recuperación?
  • ¿Hay alguna forma de obtener el contenido corporal de estos estados?

PD: la versión de mi navegador es Google Chrome 70.0.3538.102 (正式 版本) (64 位)

Luna
fuente
Esto significa que está recibiendo una respuesta de api, pero no es un json válido, ¿está enviando todos los parámetros requeridos en la solicitud?
kiranvj
@kiranvj Verifiqué mis datos, el mismo contenido, acabo de cambiar el código de estado a 200 para obtenerlo correctamente.
Luna
1
Tengo el mismo problema pero mi estado es 200, ¿cómo lo resolvió eventualmente?
DavSev
@DavSev Para un código de estado específico, obtengo los datos de retorno a través de axios
Luna
1
también sucede con 200.
schlingel

Respuestas:

175

También encontré este error pero descubrí que no está relacionado con el estado de Respuesta, el verdadero problema es que solo puedes consumir Response.json()una vez, si lo estás consumiendo más de una vez, el error ocurrirá.

como abajo:

    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

    }

Entonces la solución es evitar consumir Response.json()más de una vez en thenbloque.

Wayne Wei
fuente
5
podría response.clone()antes de consumirlo.
Balduran
Agradable. Tuve un console.log(r.json()); return r.json();que lo rompió.
mewc
2
Gracias, funcionó para mí ... ¿alguien puede explicar este extraño comportamiento?
Sachin
74

Usar Response.clone()para clonarResponse

ejemplo

fetch('yourfile.json').then(res=>res.clone().json())
Criss Anger
fuente
19
Esto funcionó muy bien para mí, pero ¿alguien entiende por qué es necesario? Lo busqué y veo que a veces, una vez que un lector comienza a leer Response.body, se bloquea para ese lector. Pero por lo que puedo ver (al menos en mi código), nada ha comenzado a leerse ... ¿hay una explicación de cómo la secuencia legible podría bloquearse automáticamente?
jenming
5
Tuve el mismo problema, pero descubrí que tenía "res.json ()" en mi panel de reloj en las herramientas de desarrollo de Chrome, ¡que se estaba resolviendo antes del código en sí!
FelipeDrumond
1
¿esperar lo? @FelipeDrumond ¡eso es un error loco (no)!
George Mauer
@GeorgeMauer Bueno, si solo podemos ejecutar response.json () una vez y el panel de vigilancia de las herramientas de desarrollo de Chrome lo ejecuta antes de su código, tendrá una excepción porque, bueno, ¡ejecutó response.json () dos veces!
FelipeDrumond
Referencia MDN
foxiris
7

El método de respuesta como 'json', 'text' se puede llamar una vez y luego se bloquea. La imagen de respuesta publicada muestra que el cuerpo está bloqueado. Esto significa que ya ha llamado al 'entonces', 'captura'. Para volver a amar esto, puede intentar lo siguiente.

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))
Bradia
fuente
3

Sé que es demasiado tarde pero puede ayudar a alguien:

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

Yo también me metí en esto. Pero esto funcionó para mí.

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

buena suerte

Ankit Kataria
fuente
Un ejemplo sobre recuperación en MDN github.com/mdn/fetch-examples/blob/master/fetch-json/…
Magaesh
1

Estaba reutilizando accidentalmente un objeto de respuesta, algo similar a esto:

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

Esta línea:

const json2 = await response.json();

Debería haber sido (respuesta2 en lugar de la respuesta1 agotada):

const json2 = await response2.json();

Reutilizar la respuesta anterior no tenía sentido y fue un error tipográfico de código sucio ...

Jeremy Bunn
fuente
1

Esto funcionó para mi

response.json().then(data => {
  // use data
})
Beau Barker
fuente
0

Como se menciona en la pregunta cuando intenta utilizar el mismo objeto de respuesta, su cuerpo está a punto de bloquearse debido al estado del objeto. Lo que puede hacer es capturar el valor del objeto de respuesta y luego intentar tener alguna operación en él (. Then ()). Siga el código a continuación,

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 { ---- })
        }
    } 
}
Juhil Somaiya
fuente