Handling Errors
Applications that implement loading and saving of data typically wish to provide solid error handling. A number of error conditions can occur that are outside the applications control (missing files, unreadable files, incorrectly formatted files etc).Being able to catch these errors and surface meaningful error messages to the end user is important.
Ideally the applications wants a simple and clean API for performing loading, and still have the confidence that errors are caught and meaningful messages are presented to the user.
Types of Errors
There are three main types of errors that arise when attempting to load a data resource:
- There is some kind of network/resource access error, preventing the request for data from being completed.
- A request is sent to a server, but the server is unable to service the request due to some error condition (often illegal access tokens or request parameters) and sends an error response.
- The server returns data, but the parser is unable to parse it (perhaps due to the data being malformatted, or formatted according to an unsupported version of that format).
loaders.gl can detect all of these error conditions and report the resulting errors in a unified way (the errors will be available as exceptions or rejected promises depending on your async programming style, see below).
Error Messages
loaders.gl aims to produce concise, easy-to-understand error messages that can be presented directly to the end user.
- When the
fetch
call fails, any exceptions are passed to the user, - When a loader fails, it generates an error message.
- For server error responses, some basic information about the error is compiled into an error message (using e.g.
response.status
,response.url
and occasionallyresponse.text
).
Note that while servers often send some information about errors in
response.text()
when setting HTTP error codes, there are no universally accepted conventions for how servers format those error messages. Server error messages can be JSON or XML encoded for machine consumption, or generated in HTML or clear text format intended to be displayed directly to end user. Even when JSON or XML coded,
loaders.gl makes a "best effort" attempt to extract some meaningful error message from server responses. If you know how your specific service formats errors and want to extract these in a way that you can present to the user, you may want to take control of the fetch
calls and Response
status checking, see below.
parse Error Handling
parse
accepts fetch Response
objects, and parse
will check the status of the Response
before attempting to parse, and generate an exception if appropriate.
Handling Errors from Async Functions
Note that parse
is an async function, and in JavaScript, errors generated by async functions will be reported either as an exception or as a rejected promise, depending on how the async funtion was called (using promises or the await
keyword):
When using await
, errors are reported as exceptions
try {
const response = await fetch(url);
const data = await parse(response);
} catch (error) {
console.log(error);
}
A rejected promise is generated when using Promise.then
.
fetch(url)
.then((response) => parse(response))
.catch((error) => console.log(error));
Also note that the Javascript runtime seamlessly converts errors between exceptions and promises in mixed code.
fetch Error Handling
loaders.gl is designed around the use of the modern JavaScript fetch
API, so for additional context, it may help to review of how the JavaSctipt fetch
function handles errors.
fetch
separates between "network errors" that can be detected directly (these cause the fetch
to throw an exception) and server side errors that are reported asynchronously with HTTP status codes (in this case the Response
object offers accessors that must be called to check if the operation was successful before accessing data).
Example: "manually" checking separately for fetch network errors and server errors:
// Check for network error
let response;
try {
response = await fetch(url);
} catch (error) {
console.log('Network error');
}
// Check for server error
if (!response.ok) {
console.log(`fetch failed with status ${response.status}`);
}
Note that servers often sends a message providing some detail about what went wrong, and that message can be accessed using the standard (asynchronous) response.text()
or response.json()
methods.
if (!response.ok) {
const errorMessage = await response.text();
// Custom parsing can be done here, if you know how your particular service formats errors
console.log(`fetch failed with status ${errorMessage}`);
}