DEV Community

Mark
Mark

Posted on

JavaScript Exception Handling

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

try {
    let name = 'hello';
    console.log(nam);
} catch(e) {
    console.log('caught', e);
}
Enter fullscreen mode Exit fullscreen mode

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

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

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

2.3 Can’t catch asynchronous error.

try {
  setTimeout(() => {
    undefined.map(v => v);
  }, 1000)
} catch(e) {
  console.log('caught ', e);
}
Enter fullscreen mode Exit fullscreen mode

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

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')
Enter fullscreen mode Exit fullscreen mode

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

window.onerror = function(message, source, lineno, colno, error) {
  console.log('caught', {message, source, lineno, colno, error});
  return true;
}

let name = 'hello;
console.log(nam);
Enter fullscreen mode Exit fullscreen mode

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

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)
Enter fullscreen mode Exit fullscreen mode

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

3.4 Try Static Resource Loading Exception with window.onerror

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

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.

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

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:

window.addEventListener("unhandledrejection", function(e){
  e.preventDefault();//prevent default console output
  console.log('caught:', e);
  return true;
});
Promise.reject('promise error');
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)