javascript fetch - не удалось выполнить json в ответе: основной поток заблокирован

112

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

Uncaught (в обещании) TypeError: не удалось выполнить 'json' в 'Response': основной поток заблокирован

Я показал содержимое возвращенного объекта ответа следующим образом:

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

Но я все еще могу использовать его несколько месяцев назад.

У меня следующий вопрос:

  • Это просто поведение браузера Chrome или стандартные изменения выборки?
  • Есть ли способ получить содержимое тела этих состояний?

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

Луна
источник
Это означает, что вы получаете ответ от api, но это недействительный json, вы отправляете все необходимые параметры в запросе?
kiranvj
@kiranvj Я проверил свои данные, тот же контент, я просто изменил код статуса на 200, чтобы получить его правильно.
Luna
1
У меня такая же проблема, но мой статус 200, как вы ее в итоге решили?
DavSev
@DavSev Для определенного кода состояния я получаю данные возврата через axios
Луна,
1
бывает и с 200.
schlingel 03

Ответы:

182

Я тоже встречал эту ошибку, но выяснил, что она не связана с состоянием Response, реальная проблема в том, что вы можете потреблять 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блоке.

Уэйн Вэй
источник
6
вы могли бы, response.clone()прежде чем употреблять его.
balduran
Ницца. у меня был console.log(r.json()); return r.json();сломанный.
mewc
2
Спасибо, у меня сработало ... Кто-нибудь может объяснить это странное поведение?
Сачин,
Спасибо, чувак, это отлично сработало для меня
Ронни Перес,
75

Использовать Response.clone()для клонированияResponse

пример

fetch('yourfile.json').then(res=>res.clone().json())
Крисс Гнев
источник
19
У меня это отлично сработало, но кто-нибудь понимает, зачем это нужно? Я поискал его и вижу, что иногда, когда читатель начинает читать Response.body, он привязывается к этому читателю. Но из того, что я вижу (по крайней мере, в моем коде), ничего никогда не начиналось читать ... есть ли объяснение того, как читаемый поток может быть автоматически заблокирован?
jenming
6
У меня была такая же проблема, но я обнаружил, что на моей панели часов в инструментах Chrome dev был "res.json ()", который решался до самого кода!
FelipeDrumond
1
чего ждать? @FelipeDrumond - это сумасшедшая (не) ошибка!
Джордж Мауэр
@GeorgeMauer Что ж, если мы можем запустить response.json () только один раз, а панель просмотра инструментов Chrome dev запускает это перед вашим кодом, у вас будет исключение, потому что вы дважды запускали response.json ()!
Фелипе Драмонд,
Ссылка MDN
foxiris
8

Метод ответа, такой как '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))
Брадия
источник
4

Я знаю, что уже поздно, но это может кому-то помочь

let response = await fetch(targetUrl);
let data = await response.json();
Шериф
источник
Именно то, что мне нужно для решения этого вопроса, используя синтаксис async / await, спасибо!
ttemple
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/…
Магаеш
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();

Должно было быть (response2 вместо использованного response1):

const json2 = await response2.json();

Повторное использование предыдущего ответа не имело смысла, и это была опечатка грязного кода ...

Джереми Банн
источник
1

Это сработало для меня

response.json().then(data => {
  // use data
})
Бо Баркер
источник
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 { ---- })
        }
    } 
}
Джухил Сомайя
источник