JavaScript Exception Handling
Tags: javascript, tutorial
Published: 2024-02-24 04:54:38

Exceptions in JavaScript will stop subsequent code’s running if it is not handled correctly.

**1. Exception Types**

- Syntax Error and Code Exception
- Asynchronous Request Exception
- Static Resource Loading Exception
- Promise Exception
- Iframe Exception
- Cross Domain Error
- Crash and Freeze

**2. Try-Catch Misunderstanding**

Try-Catch only catch run time exception, It can't catch syntax error and asynchronous error.

2.1 catch run time exception

```javascript
try {
    let name = 'hello';
    console.log(nam);
} catch(e) {
    console.log('caught', e);
}
```

Output: caught ReferenceError: nam is not defined at …

2.2 Can’t catch syntax error, let’s delete one quotation mark to make syntax error

```javascript
try {
    let name = 'hello; // delete one quotation here
    console.log(nam);
} catch(e) {
    console.log('caught', e);
}
```

Output: Uncaught SyntaxError: Invalid or unexpected token (at…

2.3 Can’t catch asynchronous error.

```javascript
try {
  setTimeout(() => {
    undefined.map(v => v);
  }, 1000)
} catch(e) {
  console.log('caught ', e);
}
```

Output: Uncaught TypeError: Cannot read properties of undefined (reading ‘map’) at…

You can see the exception in timeout not be caught, have a notice here.

**3. window.onerror Is Not Everything**

When js has run time error, window will trigger an error event of the ErrorEvent, and execute window.onerror().

3.1 Try run time exception with window.onerror

```javascript
window.onerror = function(message, source, lineno, colno, error) {
  console.log('caught', {message, source, lineno, colno, error});
  return true; // cancel the default behavior of the error event of Window
}
 
let name = 'hello';
console.log(nam);
console.log('test')
```

Output: caught {message: ‘Uncaught ReferenceError: nam is not defined’, source:….

You can see, when canceled, the error won’t appear in the console, but the current script will still stop executing.

3.2 Try syntax error with window.onerror

```javascript
window.onerror = function(message, source, lineno, colno, error) {
  console.log('caught', {message, source, lineno, colno, error});
  return true;
}
 
let name = 'hello;
console.log(nam);
```

Output: Uncaught SyntaxError: Invalid or unexpected token at…

It means window.onerror can’t catch syntax error.

3.3 Try asynchronous error with window.onerror

```javascript
window.onerror = function(message, source, lineno, colno, error) {
  console.log('caught', {message, source, lineno, colno, error});
  return true;
}
 
setTimeout(() => {
  let name = 'hello';
  console.log(nam);
  console.log('test')
}, 1000)
```

Output: caught {message: ‘Uncaught ReferenceError: nam is not defined’, source:…

3.4 Try Static Resource Loading Exception with window.onerror

```javascript
<script>
  window.onerror = function(message, source, lineno, colno, error) {
    console.log('caught', {message, source, lineno, colno, error});
    return true;
  }
</script>
<img src="./1.png">
```

Output: 404 Not found

It means window.onerror can’t catch 404 error.

Please notice, window.onerror must insert before every js script.

Now we are clear, in practice, onerror is mainly used to catch unexpected errors, while try-catch is used to monitor specific errors in predictable situations, and the combination of the two is more efficient.

Now the question is, how to catch 404 error?

**4. window.addEventListener**

When a resource (such as a picture or a script) fails to load, the element that loads the resource will trigger an error event of the Event interface, and execute the onerror() handler on the element. These error events do not bubble up to window , but can be caught by window.addEventListener.

```javascript
<script>
  window.addEventListener('error', (error) => {
    console.log('caught', error);
  }, true)
</script>
<img src="./1.png">
```

Since the network request exception does not cause event bubbling, it must be captured in the capture phase. However, although this method can capture the exception of the network request, it cannot judge whether the HTTP status is 404 or other such as 500, etc. Therefore, it is necessary to cooperate with the server log to conduct investigation and analysis.

**5. Promise Catch**

Errors thrown from Promise without catch cann’t be caught by onerror or try-catch, so don’t forget to write catch to handle the thrown exception in Promise.

Solution: In order to prevent missed Promise exceptions, it is recommended to add a handler for unhandledrejection globally to handle Uncaught Promise Error globally. How to use:

```javascript
window.addEventListener("unhandledrejection", function(e){
  e.preventDefault();//prevent default console output
  console.log('caught：', e);
  return true;
});
Promise.reject('promise error');
```

**6. Conclusion**

- Add Try-Catch for Suspicious Code
- Globally handle JS exception use window.onerror
- Globally handle static resource 404 use window.addEventListener
- Globally handle un-caught promise exception use unhandledrejection