Skip to content

Instantly share code, notes, and snippets.

@mmazzarolo
Created June 29, 2022 16:49
Show Gist options
  • Save mmazzarolo/9bd0b1be9f10c90a35287275401d91c4 to your computer and use it in GitHub Desktop.
Save mmazzarolo/9bd0b1be9f10c90a35287275401d91c4 to your computer and use it in GitHub Desktop.
Handling localStorage errors (such as quota exceeded errors)
/**
* Determines whether an error is a QuotaExceededError.
*
* Browsers love throwing slightly different variations of QuotaExceededError
* (this is especially true for old browsers/versions), so we need to check
* different fields and values to ensure we cover every edge-case.
*
* @param err - The error to check
* @return Is the error a QuotaExceededError?
*/
function isQuotaExceededError(err: unknown): boolean {
return (
err instanceof DOMException &&
// everything except Firefox
(err.code === 22 ||
// Firefox
err.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
err.name === "QuotaExceededError" ||
// Firefox
err.name === "NS_ERROR_DOM_QUOTA_REACHED")
);
}
/**
* Determines whether a storage implementing the Web Storage API (localStorage
* or sessionStorage) is supported.
*
* Browsers can make the storage not accessible in different ways, such as
* not exposing it at all on the global object or throwing errors as soon as
* you access/store an item.
* To account for all these cases, we try to store a dummy item using a
* try & catch to analyze the thrown error.
*
* @param webStorageType - The Web Storage API to check
* @return Is the storage supported?
*/
function isStorageSupported(
webStorageType: "localStorage" | "sessionStorage" = "localStorage"
): boolean {
let storage: Storage | undefined;
try {
storage = window[webStorageType];
if (!storage) {
return false;
}
const x = `__storage_test__`;
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (err) {
// We acknowledge a QuotaExceededError only if there's something
// already stored.
const isValidQuotaExceededError =
isQuotaExceededError(err) && storage.length > 0;
return isValidQuotaExceededError;
}
}
// Example usage
(function app() {
if (!isStorageSupported("localStorage")) {
// Handle the case where the localStorage API is not supported.
// One thing you might wanna do, for example, is to start using a different
// storage mechanism (in-memory, a remote db, etc.)
return;
}
// You can now use setItem, knowing that if it throws, it can only mean that
// localStorage is full.
try {
localStorage.setItem(keyName, keyValue);
} catch (err) {
// Handle the case where localStorage is full.
}
});
@mmazzarolo
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment