Reputation: 2452
I am throw
ing an exception from the onload
method of my XMLHttpRequest
object. However I am unable to catch
that error using a try
catch
block.
I have the following code in my _fetch(url, callback)
function:
const xhr = new XMLHttpRequest()
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
// if (xhr.status === 200) callback(xhr.response)
// throw a 'custom' error if the server responds with 501
if (xhr.status === 501) throw new Error('Answer not found') /
}
}
// rest of the fn
Then, I am using the _fetch
function:
try {
_fetch(endPoint, response => console.log(response))
} catch (error) { // error not caught
console.log(error)
}
However, the error is not caught and instead an error is thrown — Uncaught Error: Answer not found
try
catching
ing the send()
method of the xhr
object in _fetch
try
catching
ing the open()
method of the xhr
object in _fetch
onerror
method of the xhr
object — won't work because the request is completed successfullySo, how can I catch
that error?
To try out the full code, check out this fiddle.
throw
the error in the onload
method?I am getting data from a certain API, and due to some restriction, I can't use fetch
. I am using XMLHttpRequest
instead. The server responds with the error code 501 - Not Implemented
if the query I have sent cannot be answered.
Thus I need to pick out that error code, and carry out some functionality.
Obviously, there are other possible ways to achieve my end goal, but I'm finding it hard to wrap my head around why this won't work. I have read up on both throw
and XMLHttprequest
but I may have a misunderstanding of how one of them works.
Upvotes: 4
Views: 5074
Reputation: 1803
You absolutely can use fetch to make this not only easier on yourself, but to work with the errors. JSFiddle link below this code.
const url = `http://api.wolframalpha.com/v1/result?appid=H2R834-AUAJXG9KRV&i=%3F`
fetch(`https://cors-anywhere.herokuapp.com/${url}`)
.then(res => {
console.log(res.status)
if (res.status == 200) {
return res.json()
}
else if (res.status == 501) {
throw new Error("Answer not found")
}
else {
throw new Error("Some other status code")
}
})
.then(json => {
console.log(json)
})
.catch(err => {
console.error(err)
})
https://jsfiddle.net/mparson8/ug1hoks8/9/
Upvotes: 5
Reputation: 953
While you can use a library to make your life easier,
XMLHttpRequest
onXXXX are actually event handlers, onload being only one of many possible events. The full list is here: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Events
In this case, you have a missing error handler:
xhr.onerror( ... )
Also, if you have access to a modern browser, please use
xhr.addEventListener('load'|'error'|..., ... )
instead. This actually allows multiple handlers, removing handlers, etc.
Regarding your sample code:
function _fetch(url, callback)
const xhr = new XMLHttpRequest()
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
// if (xhr.status === 200) callback(xhr.response)
// throw a 'custom' error if the server responds with 501
if (xhr.status === 501) throw new Error('Answer not found')
// This can never be caught because async functions break the stack.
// Intuition: If you can't return it, you can't throw either.
}
}
// rest of the fn
Then, I am using the _fetch function:
try {
_fetch(endPoint, response => console.log(response))
} catch (error) { // error not caught
console.log(error)
}
In this case, you need to modify the fetch's callback to use two parameters, in a similar style to node.js
In particular: _fetch(endPoint, (err, resp) => ... )
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
// if (xhr.status === 200) callback(null, xhr.response)
// throw a 'custom' error if the server responds with 501
if (xhr.status === 501) callback(new Error('Answer not found'), null);
}
}
Of course, the smart way is to use promises (or a library). Ensure you call either resolve or reject, at least once.
function _fetch(endpoint, callback) {
return new Promise( (resolve, reject) => {
xhr.onload = function () {
if (xhr.readyState === xhr.DONE) {
// if (xhr.status === 200) resolve(xhr.response)
// throw a 'custom' error if the server responds with 501
if (xhr.status === 501) reject(new Error('Answer not found'));
}
}
});
}
This allows you to use it as follows:
_fetch(endpoint)
.then ( res => console.log('result', res) )
.catch( e => console.log('error', e);
Upvotes: -1