Reputation: 8370
I have a function in my front end app which calls my node.js backend server:
Client function:
this.geocode = (placeName) => {
const url = '/api/twitter/geocode?' + 'query=' + encodeURIComponent(placeName);
return fetch(url)
.then(processResponse)
.catch(handleError)
}
// API Helper methods
const processResponse = function (response) {
if (response.ok) {
console.log(response);
return response.json()
}
throw response;
}
const handleError = function (error) {
if (error.json) {
error.json().then(error => {
console.error('API Error:', error.message || error)
})
} else {
console.error('API Error:', error.message || error)
}
}
Server route:
app.get('/api/twitter/geocode', (req, res) => {
var parameters = {
query: req.query.query
}
Twitter.get('geo/search', parameters)
.then(response => {
console.log("RESPONSE:")
console.log(response);
// check if there is a place for the given query
if(response.date.places.length > 0){
res.send(response.data.result.places[0].bounding_box.coordinates[0][0]);
}
res.send()
})
.catch(e => res.status(500).send('Something broke!')
)
});
There is a problem when placeName
is the name of a place that doesn't exist (or at least that Twitter doesn't know about). The console.log(response)
in the backend shows me that such a request to the Twitter api leads to a return message without place data:
{ data:
{ result: { places: [] },
query:
{ url: 'https://api.twitter.com/1.1/geo/search.json?query=FOOBARTOWN',
type: 'search',
params: [Object] } },
resp:
/*etc...*/
As you can see, places
is an empty list. This response causes a crash in my frontend. I would like to know why. Look at the error message:
const handleError = function (error) {
if (error.json) {
> error.json().then(error => {
console.error('API Error:', error.message || error)
})
} else {
And some other console outputs in the browser:
GET http://localhost:3000/api/twitter/geocode?query=FOOBARTOWN 500 (Internal Server Error) (model.js:197)
Uncaught (in promise) SyntaxError: Unexpected token S in JSON at position 0
at handleError (model.js:214)
It seems like we are getting error 500
. But why? My server hasn't failed. There's no error message in the node.js console.
Also, it seems like the program ends up in handleError
, and then fails to convert the error to json.
this.geocode
gets an empty message, I don't crash, and return that empty message (so I can check for an empty message and act appropriately in my React.js component)?Upvotes: 0
Views: 2150
Reputation: 40444
Why does it go to handleError? What's the error?
Your server is sending a 500 status code, with Something broke!
as response body.
An when you try to use res.json()
on a non JSON string you get:
Uncaught SyntaxError: Unexpected token S in JSON at position 0
The line if(error.json)
is not doing what you think it does. handleError
is being called when response.ok
is false, since you're throwing the fetch response object otherwise, in that case error
argument will be a fetch response that implements Body, which has a json
method, even if the body isn't a JSON, which is your case.
Your handleError
can be written like this, where you will handle fetch
errors and non 2xx responses.
const handleError = async function(error) {
if(error instanceof Response) {
if(error.headers.get('content-type').includes('application/json'))
error = await error.json();
else error = await error.text();
}
console.error('API Error:', error.message || error)
}
Why does it say my server failed (error 500)?
Place a console.log(e)
on Twitter.get().catch
and you'll find out.
Your Twitter.get().then
is also wrong, since you're sending the response twice.
if(response.date.places.length > 0){
res.send(response.data.result.places[0].bounding_box.coordinates[0][0]);
}
res.send()
Should be:
if(response.date.places.length > 0)
return res.send(response/*...*/);
res.send()
Upvotes: 3