Skip to content

Instantly share code, notes, and snippets.

@RohitRox
Last active March 7, 2022 06:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RohitRox/d0df7bdcf237ed3a4a50af9e9824eaed to your computer and use it in GitHub Desktop.
Save RohitRox/d0df7bdcf237ed3a4a50af9e9824eaed to your computer and use it in GitHub Desktop.
Beautiful Errors in Javascript
// Try/Catch Basics
try {
//something that causes an error
} catch (err){
// error data
console.log(err.name)
console.log(err.message)
// checking for specific type
console.log(err instanceof(ReferenceError))
}
// Example
try {
undefined+SOME_VARIABLE
} catch(err) {
// Javascript error types
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types
console.log(err.name, err.message)
}
// Throwing errors in js
throw new Error("Not good.")
// Making our own beautiful errors
class TokenError extends Error {
constructor(message) {
super(message || 'Invalid Token');
this.name = this.constructor.name;
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(message)).stack;
}
}
}
try {
throw new TokenError
// throw new TokenError("Expired Token")
} catch(err) {
console.log(err.name, err.message)
}
// Adding more data and info
class TokenExtendedError extends Error{
constructor(message, params) {
super(message || 'Invalid Token');
this.name = this.constructor.name;
this.code = params.code
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(message)).stack;
}
}
}
try {
throw new TokenExtendedError('Token is empty', { code: 'TokenEmptyError' })
} catch(err) {
console.log(err.name, err.message, err.code, err instanceof(TokenExtendedError))
}
// With the knowledge of custom error
// we now can design our own error types and
// catch and handle them accordingly
// and also set appropriate data/attributes for catching/logging/analyzing purposes
// we can also see that various standard libraries and sdk implements their own errors and presents us with their own error data and attributes
// For eg: with axios we get response attribute in error, which holds response data and status code
// aws sdk throws an error with code attribute
const axios = require('axios');
// Handling axios errors
const callFetchPostsError = async () => {
try {
await axios.get('https://reqres.in/api/unknown/23');
} catch (err) {
// handle error based on response data
if (err.response.data.message) {
console.log("Will do something with: ", err.response.data.message)
} else {
console.log("Oops! Something terribly went wrong. Prolly not axios Error.")
}
// handle error based on status codes
switch (err.response.status) {
case 404:
console.log("Server handled this but it's a not found.")
break;
case 500:
console.log("Server has no idea what's going on there.")
break;
default:
console.log("Something weird")
}
}
}
callFetchPostsError()
// Handling aws sdk error
// a fake aws sdk's function
const FakeAWSFunc = (success) => {
if (success)
return Promise.resolve({ some: 'data'})
else
return Promise.reject(
new AWSError('Promise rejected', { code: 'NotAuthorizedException' })
)
}
// fake aws custom error
class AWSError extends Error{
constructor(message, params) {
super(message || 'AWS Error');
this.name = this.constructor.name;
this.code = params.code
if (typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(message)).stack;
}
}
}
const callFakeAWS = async () => {
try {
const data = await FakeAWSFunc(false);
console.log(data)
} catch(err) {
// handle specific error
if (['NotAuthorizedException', 'ValidationException'].includes(err.code)) {
console.log("I know what's going on. Will do thing accordingly.")
} else {
console.log("Have no idea. Prolly do a generic thing.")
}
// or handle based on type
if (err instanceof(AWSError)) {
} else {
}
}
}
callFakeAWS();
// Handling multiple error types
const codeWithMultipleTypes = async () => {
try {
throw new TokenError
// error thrown from above line, code below this does not get executed, not .then blocks needed
const dd = await FakeAWSFunc()
} catch(err) {
// check here type of error anf handle accordingly
console.log(err instanceof(TokenError))
console.log(err instanceof(AWSError))
}
}
codeWithMultipleTypes()
// Testing
// Use mockImplementation in jest
// sucessfull operation
AWSService.associateSoftwareToken.mockImplementation(() => {
return Promise.resolve({})
})
// fail with code that identifies NotAuthorizedException error
AWSService.associateSoftwareToken.mockImplementation(() => {
return Promise.reject({ message: 'Message', code: 'NotAuthorizedException' })
})
// generic fail with just message
AWSService.associateSoftwareToken.mockImplementation(() => {
return Promise.reject({ message: 'Message' })
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment