Перечитать тело ответа из выборки JavaScript

fetch() возвращает обещание, которое (в случае успеха) разрешается в Response объект. Очень распространенная вещь, которую нужно сделать, это немедленно позвонить Response.json() преобразовать тело ответа в объект JSON.

Если тело ответа не является допустимым JSON, то Response.json() обещание не выполняется с ошибкой. Сообщение является чем-то вроде:

Неожиданный токен X в JSON в позиции 0

Это не очень полезно при диагностике проблемы; в идеале я хотел бы видеть контент с сервера (что часто является сообщением об ошибке).

Тем не менее, кажется, что вы можете только читать поток в Response.body один раз (по крайней мере, в Chrome). (Там даже только для чтения Response.bodyUsed флаг.) Это уже произошло, когда Response.json() пытается преобразовать тело в JSON, поэтому тело оказывается потерянным навсегда в случае сбоя анализа JSON.

Есть ли способ восстановить исходное тело ответа... если не считать его вручную (а затем преобразовать в JSON), когда оригинал fetch Обещание разрешается?

5 ответов

Решение

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

let clone = response.clone();

В качестве альтернативы используйте Response.body.getReader() который возвращает ReadableStream читать Response как поток, TextDecoder() преобразовать Uint8Array поток данных в текст.

Мне приходилось иметь дело с API, который иногда вызывал ошибку в ответе JSON - до возвращения response.json() Я сделал клон объекта ответа. используя блок catch, я могу определить, является ли ошибка SyntaxError, и приступить к ее исправлению, используя текстовый результат клона ответа

немного так:

var brokenJson = function (url) {
    var responseCopy;
    return fetch(url)
    .then(function (response) {
        responseCopy = response.clone();
        return response.json();
    }).catch(function (err) {
        if (err instanceof SyntaxError) {
            return responseCopy.text()
            .then(function(data) {
                return fixJson(data);
            });
        }
        else {
            throw err;
        }
    }).then(function (json) {
        // do things
    });
};

fixJson это просто функция, которая исправляет полученные данные - в моем случае, когда он был сломан JSON, он всегда был сломан одинаково - я думаю, что у него был дополнительный ведущий {или конечный} - не могу вспомнить

Перечитав вопрос, вы, скорее всего, захотите записать ошибку на консоль, а не исправлять json - легко переписать:

var brokenJson = function (url) {
    var responseCopy;
    return fetch(url)
    .then(function (response) {
        responseCopy = response.clone();
        return response.json();
    }).catch(function (err) {
        if (err instanceof SyntaxError) {
            return responseCopy.text()
            .then(function(text) {
                console.error(text);
                throw err;
            });
        }
        else {
            throw err;
        }
    }).then(function (json) {
        // do things
    });
};

Назначение response.json() переменной и его возврат сработали для меня. clone() снова сказал, что он заблокирован.

fetch("http://localhost:3000/watchlist")
    .then(response => {
      var res = response.json();
      return res;
    })
    .then(data => {
      console.log(data);
      this.setState({ data });
    });

Как насчет?

      fetch(url).then(async response => {
    var response_text = await response.text();
    var response_data = JSON.parse(response_text);
    // do whatever you want now
    // and if the JSON.parse() failed, you still have the original response_text
}

(На самом деле другие намекали на что-то вроде этого)

я использовал JSON.parse(response.resp.data) как-то клон не работал.

Другие вопросы по тегам