javascript fetch - Не вдалося виконати 'json' у 'Response': основний потік заблоковано


107

Коли статус запиту перевищує 400 (я пробував 400, 423, 429 станів), fetch не може прочитати повернутий вміст json. Наступна помилка відображається на консолі браузера

Невпійманий (обіцяно) TypeError: Не вдалося виконати 'json' у 'Response': потік тіла заблоковано

Я показав вміст повернутого об'єкта відповіді наступним чином:

введіть тут опис зображення

Але я все ще можу використовувати це кілька місяців тому.

Моє запитання таке:

  • Це лише поведінка браузера Chrome чи стандартні зміни отримання?
  • Чи є спосіб отримати вміст у цих станах?

PS: Моя версія браузера - Google Chrome 70.0.3538.102 (正式 版本) (64 位)


Це означає, що ви отримуєте відповідь від api, але це не дійсний json, чи надсилаєте ви всі необхідні параметри у запиті?
kiranvj

@kiranvj Я перевірив свої дані, той самий вміст, я просто змінив код стану на 200, щоб отримати його правильно.
Луна

1
У мене така сама проблема, але мій статус 200, як ви врешті вирішили?
DavSev

@DavSev Для конкретного коду стану я отримую дані повернення через axios
Luna

1
це трапляється і з 200.
schlingel

Відповіді:


175

Я теж зустрів цю помилку, але виявив, що вона не пов'язана зі станом відповіді, справжня проблема полягає в тому, що ви можете споживати лише 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

    }

Тож рішення полягає в тому, щоб уникнути споживання Response.json()більше одного разу в thenблоці.


5
Ви могли б, response.clone()перш ніж споживати його.
balduran

Приємно. у мене був console.log(r.json()); return r.json();який його зламав.
mewc

2
Дякую, це спрацювало для мене ..... хтось може пояснити цю дивну поведінку?
Сачин

74

Використовуйте Response.clone()для клонуванняResponse

приклад

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

19
Для мене це чудово працювало, але хтось розуміє, чому це потрібно? Я шукав це, і я бачу, що іноді, коли читач починає читати Response.body, він замикається на цьому читачеві. Але з того, що я бачу (принаймні в моєму коді), ніколи нічого не починалося читати ... чи є пояснення того, як читабельний потік може автоматично заблокуватися?
jenming

5
У мене була та ж проблема, але я дізнався, що у мене на панелі годинника в інструментах chrome dev був "res.json ()", який вирішувався до самого коду!
FelipeDrumond

1
чекати, що? @FelipeDrumond - це божевільна (не) помилка!
Джордж Мауер,

@GeorgeMauer Ну, якщо ми можемо запустити response.json () лише один раз, а панель спостереження chrome dev tools працює так, як перед вашим кодом, у вас буде виняток, адже добре, ви запустили response.json () двічі!
ФеліпеДрумонд

Довідка MDN
foxiris

7

Метод відповіді на зразок 'json', 'text' можна викликати один раз, а потім він блокується. Розміщене зображення відповіді показує, що тіло заблоковано. Це означає, що ви вже називали "тоді", "зловити". Щоб полюбити це, ви можете спробувати наступне.

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

Або

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

3

Я знаю, що пізно, але це може комусь допомогти:

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

2

Я теж застряг у цьому. Але це спрацювало для мене.

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

Щасти


Приклад про отримання в MDN github.com/mdn/fetch-examples/blob/master/fetch-json/…
Magaesh

1

Я випадково повторно використовував об'єкт відповіді, щось подібне до цього:

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

Мав бути (відповідь2 замість використаної відповіді1):

const json2 = await response2.json();

Повторне використання попередньої відповіді не мало сенсу, і це була брудна помилка коду ...



0

Як зазначалося у питанні, коли ви намагаєтесь використовувати той самий об’єкт відповіді, ваше тіло ось-ось заблокується через стан об’єкта. Що ви можете зробити, це захопити значення об’єкта відповіді, а потім спробувати виконати над ним якусь операцію (.then ()). Будь ласка, дотримуйтесь наведеного нижче коду,

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 { ---- })
        }
    } 
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.