10
Author: Ashish Lahoti
Translator: Front-end Xiaozhi
Source: codingnconcept

If you have dreams and dry goods, search [Moving the World] Follow this brush bowl wisdom who is still washing dishes in the early morning.

This article has been included in GitHub https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-line manufacturers.

In today's content, let's learn about error handling using try , catch , finally , and throw . We'll also talk about the built-in error objects in JS ( Error , SyntaxError , ReferenceError , etc.) and how to define custom errors.

1. Use try..catch..finally..throw

To handle errors in JS, we mainly use the try , catch , finally and throw keywords.

  • try block contains the code we need to check
  • The keyword throw is used to throw custom errors
  • catch Block handling of caught errors
  • finally block is the final result. No matter what, a block that will be executed, you can do some things that require aftermath in this block.

1.1 try

Each try block must be associated with at least one catch or finally block, otherwise a SyntaxError error will be thrown.

We verify with the try block alone:

try {
  throw new Error('Error while executing the code');
}
ⓧ Uncaught SyntaxError: Missing catch or finally after try

1.2 try..catch

It is recommended to use try with the catch block, which gracefully handles errors thrown by the try block.

try {
  throw new Error('Error while executing the code');
} catch (err) {
  console.error(err.message);
}
➤ ⓧ Error while executing the code

1.2.1 try..catch with invalid code

try..catch cannot catch invalid JS code, for example the following code in the try block is syntactically wrong, but it will not be caught by the catch block.

try {
  ~!$%^&*
} catch(err) {
  console.log("这里不会被执行");
}
➤ ⓧ Uncaught SyntaxError: Invalid or unexpected token

1.2.2 try..catch and asynchronous code

Likewise, try..catch cannot catch exceptions thrown in asynchronous code, such as setTimeout :

try {
  setTimeout(function() {
    noSuchVariable;   // undefined variable
  }, 1000);
} catch (err) {
  console.log("这里不会被执行");
}

ReferenceError will be raised after 1 second:

➤ ⓧ Uncaught ReferenceError: noSuchVariable is not defined

So, we should use try..catch inside async code to handle errors:

setTimeout(function() {
  try {
    noSuchVariable;
  } catch(err) {
    console.log("error is caught here!");
  }
}, 1000);

1.2.3 Nesting try..catch

We can also use nested try and catch blocks to throw errors upwards like this:

try {
  try {
    throw new Error('Error while executing the inner code');
  } catch (err) {
    throw err;
  }
} catch (err) {
  console.log("Error caught by outer block:");
  console.error(err.message);
}
Error caught by outer block:
➤ ⓧ Error while executing the code

1.3 try..finally

It is not recommended to use only try..finally without the catch block, see what happens below:

try {
  throw new Error('Error while executing the code');
} finally {
  console.log('finally');
}
finally
➤ ⓧ Uncaught Error: Error while executing the code

Note two things here:

  • 06227f51255546 block is executed finally try
  • Without catch block, the error will not be handled gracefully, resulting in an uncaught error

1.4 try..catch..finally

Block try...catch finally recommended.

try {
  console.log("Start of try block");
  throw new Error('Error while executing the code');
  console.log("End of try block -- never reached");
} catch (err) {
  console.error(err.message);
} finally {
  console.log('Finally block always run');
}
console.log("Code execution outside try-catch-finally block continue..");
Start of try block
➤ ⓧ Error while executing the code
Finally block always run
Code execution outside try-catch-finally block continue..

Two things to note here:

  • The code after throwing an error in block try will not be executed
  • Block finally executes even after block try throws error

finally block is typically used to clean up resources or close streams as follows:

try {
  openFile(file);
  readFile(file);
} catch (err) {
  console.error(err.message);
} finally {
  closeFile(file);
}

1.5 throw

throw statement is used to raise an exception.

throw <expression>
// throw primitives and functions
throw "Error404";
throw 42;
throw true;
throw {toString: function() { return "I'm an object!"; } };

// throw error object
throw new Error('Error while executing the code');
throw new SyntaxError('Something is wrong with the syntax');
throw new ReferenceError('Oops..Wrong reference');

// throw custom error object
function ValidationError(message) {
  this.message = message;
  this.name = 'ValidationError';
}
throw new ValidationError('Value too high');

2. Error handling in asynchronous code

Error handling for asynchronous code can be Promise and async await .

2.1 then..catch in Promises

We can chain multiple Promises using then() and catch() to handle errors for a single Promise in the chain, like this:

Promise.resolve(1)
  .then(res => {
      console.log(res);  // 打印 '1'

      throw new Error('something went wrong');  // throw error

      return Promise.resolve(2);  // 这里不会被执行
  })
  .then(res => {
      // 这里也不会执行,因为错误还没有被处理
      console.log(res);    
  })
  .catch(err => {
      console.error(err.message);  // 打印 'something went wrong'
      return Promise.resolve(3);
  })
  .then(res => {
      console.log(res);  // 打印 '3'
  })
  .catch(err => {
      // 这里不会被执行
      console.error(err);
  })

Let's look at a more practical example, where we call an API with fetch , which returns a promise object, and we use the catch block to gracefully handle API failures.

function handleErrors(response) {
    if (!response.ok) {
        throw Error(response.statusText);
    }
    return response;
}

fetch("http://httpstat.us/500")
    .then(handleErrors)
    .then(response => console.log("ok"))
    .catch(error => console.log("Caught", error));
Caught Error: Internal Server Error
    at handleErrors (<anonymous>:3:15)

2.2 try..catch and async await

It's easier to use try..catch in async await :

(async function() {
    try {
        await fetch("http://httpstat.us/500");
    } catch (err) {
        console.error(err.message);
    }
})();

Let's look at the same example where we call an API with fetch which returns a promise object and we gracefully handle API failures with the try..catch block.

function handleErrors(response) {
    if (!response.ok) {
        throw Error(response.statusText);
    }
}

(async function() {
    try {
      let response = await fetch("http://httpstat.us/500");
      handleErrors(response);
      let data = await response.json();
      return data;
    } catch (error) {
        console.log("Caught", error)
    }
})();
Caught Error: Internal Server Error
    at handleErrors (<anonymous>:3:15)
    at <anonymous>:11:7

3. Built-in errors in JS

3.1 Error

JavaScript has built-in error objects, which are usually thrown by the try block and caught in the catch block. Error object contains the following properties:

  • name : is the name of the error, such as "Error", "SyntaxError", "ReferenceError", etc.
  • message : Message about error details.
  • stack : is the stack trace of the error for debugging purposes.

We create a Error object and look at its name and message properties:

const err = new Error('Error while executing the code');

console.log("name:", err.name);
console.log("message:", err.message);
console.log("stack:", err.stack);
name: Error
message: Error while executing the code
stack: Error: Error while executing the code
    at <anonymous>:1:13

JavaScript has the following built-in errors, which are inherited from the Error object

3.2 EvalError

EvalError represents an error about the global eval() function, this exception is no longer thrown by JS, it exists for backward compatibility.

3.3 RangeError

RangeError is raised when the value is out of range.

➤ [].length = -1
ⓧ Uncaught RangeError: Invalid array length

3.4 ReferenceError

ReferenceError is raised when referencing a variable that does not exist.

➤ x = x + 1;
ⓧ Uncaught ReferenceError: x is not defined

3.5 SyntaxError

SyntaxError is raised when you use any wrong syntax in JS code.

➤ function() { return 'Hi!' }
ⓧ Uncaught SyntaxError: Function statements require a function name

➤ 1 = 1
ⓧ Uncaught SyntaxError: Invalid left-hand side in assignment

➤ JSON.parse("{ x }");
ⓧ Uncaught SyntaxError: Unexpected token x in JSON at position 2

3.6 TypeError

Throws TypeError if the value is not of the expected type.

➤ 1();
ⓧ Uncaught TypeError: 1 is not a function

➤ null.name;
ⓧ Uncaught TypeError: Cannot read property 'name' of null

3.7 URIError

If the global URI method is used in the wrong way, URIError will be thrown.

➤ decodeURI("%%%");
ⓧ Uncaught URIError: URI malformed

4. Define and throw custom errors

We can also define custom errors this way.

class CustomError extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomError";
  } 
};

const err = new CustomError('Custom error while executing the code');

console.log("name:", err.name);
console.log("message:", err.message);
name: CustomError
message: Custom error while executing the code

We can also further enhance CustomError object to include error codes

class CustomError extends Error {
  constructor(message, code) {
    super(message);
    this.name = "CustomError";
    this.code = code;
  } 
};

const err = new CustomError('Custom error while executing the code', "ERROR_CODE");

console.log("name:", err.name);
console.log("message:", err.message);
console.log("code:", err.code);
name: CustomError
message: Custom error while executing the code
code: ERROR_CODE

Use it in the try..catch block:

try{
  try {
    null.name;
  }catch(err){
    throw new CustomError(err.message, err.name);  //message, code
  }
}catch(err){
  console.log(err.name, err.code, err.message);
}
CustomError TypeError Cannot read property 'name' of null

I'm Xiao Zhi, see you next time!


The possible bugs in the editing of cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful BUG monitoring tool Fundebug .

Original: https://codings.com/javascript/error-handling-in-javascript/

communicate with

If you have dreams and dry goods, search [Moving the World] attention to this Shawanzhi who is still washing dishes in the early morning.

This article has been included in GitHub https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-line manufacturers.


王大冶
68k 声望104.9k 粉丝