JavaScript 提取-在“ Response”上执行“ json”失败: 主体流被锁定

当请求状态大于400时(我尝试了400、423、429个状态) ,提取无法读取返回的 json 内容。浏览器控制台中显示以下错误

未捕获(在承诺中) TypeError: 未能在 “响应”: 身体流被锁定

我将返回的响应对象的内容显示如下:

enter image description here

但几个月前我还能用。

我的问题如下:

  • 这仅仅是 Chrome 浏览器的行为还是获取标准变化?
  • 有没有办法得到这些状态的主体内容?

PS: 我的浏览器版本是 Google Chrome 70.0.3538.102(正式版本)(64位)

133267 次浏览

根据 MDN,你应该使用 Response.clone():

Response接口的 clone()方法创建了一个响应对象的克隆,它们在各个方面都是相同的,但是存储在不同的变量中。clone()存在的主要原因是允许多次使用 Body对象(当它们只有一次使用时)

例子 :

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

我也遇到了这个错误,但是发现它与响应状态无关,真正的问题是你只能使用 Response.json()一次,如果你使用它不止一次,错误就会发生。

如下:

    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


}

因此,解决方案是避免在 then块中多次使用 Response.json()

响应方法,如“ json”、“ text”可以调用一次,然后它就锁定了。 上传的响应图片显示身体已被锁定。 这意味着您已经调用了“ then”,“ catch”。

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

或者

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

我不小心重用了一个响应对象,类似于这个:

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

这句话:

const json2 = await response.json();

应该是(response 2而不是用完的 response 1) :

const json2 = await response2.json();

重用之前的响应毫无意义,而且这是一个肮脏的代码输入错误..。

我也坚持这么做,但这对我很管用。

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

祝你好运

正如问题中提到的,当您试图使用相同的响应对象时,由于对象的状态,您的主体将被锁定。您可以做的是捕获响应对象的值,然后尝试对它进行一些操作(。那么(())。请按照下面的代码,

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

这招对我很管用

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

我知道已经太迟了,但它可以帮助别人:

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

fetch("xxxxxxxxxx")
.then(response => response.json())
.then(data => { console.log(data)})
.catch(error => { console.log(error)})

即使在 克隆反应之后,我仍然得到相同的错误。如果响应数据不是 JSON,那么在需要回退到文本的情况下,没有一个答案覆盖这种情况。

在我的例子中,抛出错误是因为首先我试图将响应数据作为 JSON 使用,然后如果响应不是有效的 JSON 则使用文本。

// Consuming the response data multiple times throws an error.
const response = await fetch(url, request);
try {
return await response.json();
} catch (error) {
return await response.text();
}

在一些答案的帮助下,我现在只以纯文本的形式使用一次响应数据,然后尝试将其解析为 JSON。

// This works fine because the data is being consumed only once.
const response = await fetch(url, request);
const data = await response.text();
try {
return JSON.parse(data);
} catch (error) {
console.warn(`API response is not JSON. Falling back to plain text.`, error);
return data;
}

你在 VSC 上使用 现场服务器吗? 它可能是罪魁祸首。

在类似的情况下,我恢复到 Apache 来提供静态内容,这解决了问题。