What is an exception

When users use an application, they do not get the expected results. Different exceptions may have different consequences, ranging from unpleasant to unusable, and thus causing users to lose their recognition of the product.

Why handle exceptions

  • Enhance the user experience
  • Remote Location problems
  • Unable to reproduce the problem, especially on mobile, for various reasons, system version, model, etc

What are the front-end exceptions

abnormal frequency
JavaScript exceptions (syntax errors, code errors) often
Static resource loading exception (IMG, JS, CSS) Once in a while
Ajax request exception Once in a while
Abnormal promise less
The iframe abnormal less

How to catch exceptions

try-catch

Try-catch only catches synchronous runtime errors, but not syntactic and asynchronous errors.

1. Synchronization is incorrect

try {
    kill;
} catch(err) {
    console.error('try: ', err);
}
Copy the code

Result: Try: ReferenceError: kill is not defined

2. Syntax errors cannot be caught

try {
    let name = '1;
} catch(err) {
    console.error('try: ', err);
}
Copy the code

Result: Unterminated string constant

The compiler can prevent running syntax errors.

3. Asynchronous errors cannot be caught

try {
    setTimeout(() => {
        undefined.map(v => v);
    }, 1000);
} catch(err) {
    console.error('try: ', err);
}
Copy the code

Uncaught TypeError: Cannot read property ‘map’ of undefined

window.onerror

When JavaScript runtime errors (including syntax errors) occur, the window raises an error event from the ErrorEvent interface and executes window.onerror(), which returns true, to prevent execution of the default event handler.

1. Synchronization is incorrect

/** * @param {String} message error message * @param {String} source error file * @param {Number} lineno line Number * @param {Number} colno column Number * @param {Object} error Error Object */ window.onerror = (message, source, lineno, colno, error) => {console.error(' catch exception: ', message, source, lineno, colno, error); return true; }; kill;Copy the code

Result: Uncaught ReferenceError: Kill is not defined

2. Syntax errors cannot be caught

/** * @param {String} message error message * @param {String} source error file * @param {Number} lineno line Number * @param {Number} colno column Number * @param {Object} error Error Object */ window.onerror = (message, source, lineno, colno, error) => {console.error(' catch exception: ', message, source, lineno, colno, error); return true; }; let name = '1;Copy the code

Result: Unterminated string constant

The compiler can prevent running syntax errors.

3. Asynchronous error

/** * @param {String} message error message * @param {String} source error file * @param {Number} lineno line Number * @param {Number} colno column Number * @param {Object} error Error Object */ window.onerror = (message, source, lineno, colno, error) => {console.error(' catch exception: ', message, source, lineno, colno, error); return true; }; setTimeout(() => { undefined.map(v => v); }, 1000);Copy the code

TypeError: Cannot read property ‘map’ of undefined ‘

window.addEventListener(‘error’)

When a resource (such as or

<script> window.addEventListener('error', (err) => {console.error(' catch exception: ', err); }, true); </script> <img src="./test.jpg" />Copy the code

Result: Catch exceptions: Event {isTrusted: true, type: “error”, target: img, currentTarget: Window, eventPhase: 1,… }

window.addEventListener(‘unhandledrejection’)

When a Promise is rejected and there is no Reject handler, the unhandledrejection event is emitted. This can happen under Windows, but it can also happen in workers. This is useful for debugging fallback error handling.

window.addEventListener("unhandledrejection", (err) => { err.preventDefault(); Console. error(' catch exception: ', err); }); Promise.reject('promise');Copy the code

PromiseRejectionEvent {isTrusted: true, promise: promise, reason: “promise”, type: “Unhandledrejection,” target: Windows,… }

Vue

Vue.config.errorHandler = (err, vm, info) => {console.error(' catch exception: ', err, vm, info); }Copy the code

React

React16 provides a built-in function componentDidCatch that makes it very easy to retrieve React errors.

ComponentDidCatch (error, info) {console.error(' catch exception: ', error, info); }Copy the code

However, ErrorBoundary is recommended

JavaScript errors in the user interface should not break the entire application. To solve this problem for React users, React16 introduced the new concept of “error boundaries.”

Create an ErrorBoundary.jsx component:

import React from 'react'; import { Result, Button } from 'antd'; class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, info: '' }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, info) { this.setState({ info: error + '' }); } render() {if (this.state.haserror) {// You can render any custom demote UI return (<Result status="500" title="500") subTitle={this.state.info} extra={<Button type="primary">Report feedback</Button>} /> ); } return this.props.children; } } export default ErrorBoundary;Copy the code

Use:

<ErrorBoundary>
    <App />
</ErrorBoundary>
Copy the code

Pay attention to

Error boundaries do not catch errors in:

  • Event handler
  • Asynchronous code (e.gsetTimeoutrequestAnimationFrameThe callback)
  • Server-side rendering
  • Errors raised in the error boundary itself, rather than its children

iframe

Because of the same origin policy set up by the browser, iframe exceptions cannot be handled very elegantly, and you cannot get much information from an IFrame beyond basic attributes such as its width and height.

<script> document.getElementById("myiframe").onload = () => { const self = document.getElementById('myiframe'); try { (self.contentWindow || self.contentDocument).location.href; } catch(err) {console.log(' catch exception: '+ err); }}; </script> <iframe id="myiframe" src="https://nibuzhidao.com" frameBorder="0" />Copy the code

Sentry

The industry is a very good monitoring abnormal products, the author is also using this, complete documentation.

What information needs to be reported

  • The error id
  • The user id
  • The user name
  • User IP
  • equipment
  • The error message
  • browser
  • System version
  • Application version
  • models
  • The time stamp
  • Exception level (Error, Warning, INFO)

Exception reporting

Ajax sends data

2. Create img tags dynamically

If a large amount of abnormal data causes a high load on the server, adjust the sending frequency (you can store the abnormal information on the client and set a time threshold for reporting the abnormal information) or set the collection rate (the collection rate should be set based on actual conditions. Random numbers or certain user characteristics are good choices).

The flow chart

The resources

  • How to gracefully handle front-end exceptions?
  • React
  • MDN
  • Vue

blog

Welcome to my blog