Reread a response body from JavaScript's fetch
Solution 1
Use Response.clone()
to clone Response
let clone = response.clone();
Alternatively, use Response.body.getReader()
which returns a ReadableStream
to read Response
as a stream, TextDecoder()
to convert Uint8Array
data stream to text.
Solution 2
I had to deal with an API that occasionally botched the JSON response - before returning response.json()
I made a clone of the response object. using a catch block, I can determine if the error is a SyntaxError, and proceed to fix the error using the text result of the response clone
a little like this:
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
is just a function that fixes the received data - in my case, when it was broken JSON, it was always broken the same way - I think it had an extra leading { or trailing } - can't recall
re-reading the question, you're more likely to want to log the error to the console rather than fix the 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
});
};
Solution 3
Assigning the response.json() to a variable and returning it worked for me. clone() was again saying its locked.
fetch("http://localhost:3000/watchlist")
.then(response => {
var res = response.json();
return res;
})
.then(data => {
console.log(data);
this.setState({ data });
});
Comments
-
gigimon almost 3 years
fetch()
returns promise which (if successful) resolves to aResponse
object. A very common thing to do is immediately callResponse.json()
to convert the response body to a JSON object.If the response body isn't valid JSON, then the
Response.json()
promise fails with an error. The message is something along the lines of:Unexpected token X in JSON at position 0
That's not very helpful when trying to diagnose the problem; ideally I'd like to be able to see the content from the server (which is often an error message).
However, it appears that you can only read the stream at
Response.body
once (at least in Chrome). (There's even a read-onlyResponse.bodyUsed
flag.) That has already happened whenResponse.json()
tries to convert the body to JSON, so the body appears to be lost forever in the event of a JSON parsing failure.Is there any way to recover the original response body... short of manually reading it (and then converting to JSON) when the original
fetch
Promise resolves?