2016-11-08 4 views
3

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

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

Unexpected token X in JSON at position 0

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

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

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

+1

Вместо этого вы можете вызвать 'response.text()', чтобы прочитать возвращаемые данные, даже если это недействительно JSON, и вы можете клонировать ответ, но в идеале ваш сервер должен ** всегда ** возвращать JSON, когда вы ожидаете JSON, даже ошибки должны быть возвращены как JSON. – adeneo

ответ

6

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

let clone = response.clone(); 

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

+0

@CraigWalker См. [Как добавить элементы DOM при входе в сеть?] (Http://stackoverflow.com/questions/38413400/how-can-i-append-dom-elements-as-they-stream -in-from-the-network /) – guest271314

+0

clone() выглядел как ответ, но он терпит неудачу, если вы уже вызвали .json(): "TypeError: Не удалось выполнить 'clone' on 'Response': Тело ответа уже используется » Так что resp.text(), за которым следует ручной разбор json, является одним из вариантов, но +1 для предложения Jaromanda клонировать() перед вызовом json()! – xander

+0

@xander Да, '.clone()' нужно вызывать перед чтением 'body'. Вот почему 'javascript' at Answer -' response.clone() '. Вы прочитали спецификацию https://fetch.spec.whatwg.org/#body-mixin, https://fetch.spec.whatwg.org/#bodies, https: //fetch.spec.whatwg.org/# dom-response-clone? – guest271314

1

Мне пришлось иметь дело с API, который иногда искажал ответ JSON - перед возвратом response.json() Я сделал клон объекта ответа. используя поймать блок, я могу определить, если ошибка является 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-easy rewrite:

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 
    }); 
}; 
Смежные вопросы