This is the 12th day of my participation in the August More Text Challenge. For details, see:August is more challenging

An exception is an unexpected situation that affects the final rendering result of the program. So when we develop, it is very necessary to prepare for the rainy day, abnormal monitoring, to deal with unexpected problems

Both to enhance the user experience, we developers can also remotely locate problems, especially on mobile

Although in the case of JS, exceptions generally only abort the current task, and rarely cause a crash

But exception monitoring is a perfect front-end solution must have

The following is a description of the exceptions we need to make for our front end

Abnormal monitoring

JS execution exception

  • usetry-catchError monitoring in predictable situations is recommended because it does not catch specific syntax and asynchronous errors
  • usewindow.onerror“Is better than try-catch, but it does not catch a resource load exception or an interface exception. It is recommended to catch an unexpected error

The combination of the two is better

The collected error message will print like this

window.onerror = function (msg, url, row, col, error) {
    console.table({ msg, url, row, col, error: error.stack })
    let errorMsg = {
        type: 'javascript'.// MSG = "error"; // MSG = "error"; // MSG = "error";
        msg: error && error.stack ? error.stack || msg, 
        // Number of rows where the error occurred
        row,
        // The number of columns, that is, the number of characters
        col,
        // The page where the error occurred
        url,
        // The time when the error occurred
        time: Date.now()
    }
    // Then you can save the errorMsg in an array and report it in a unified way
    // It can also be reported directly
    Axios.post({ 'https://xxxx', errorMsg })
    
    // If return true, the error is not thrown to the console
}
Copy the code

The iframe abnormal

Catching iframe exceptions is similar to JS execution

<iframe src="xxx.html"></iframe>
<script>
    window.iframe[0].onerror = function (msg, url, row, col, error) {
        // The same as the JS exception above
    })
</scrpt>
Copy the code

Abnormal resource loading

Use addEventListener(‘error’, callback, true) to catch resource loading errors during the capture phase and report them to the server

addEventListener('error'.e= > {
    const targe = e.target
    if(target ! =window) {// Collect error information here
        let errorMsg = {
            type: target.localName, // Error source name. For example, the image here is 'img'
            url: target.src || target.href, // Link to the source of the error
            / /... You can add more information if you need it
        }
        // Save the errorMsg in an array and report it in a unified way
        // Or report it directly
        Axios.post({ 'https://xxxx', errorMsg })
    }
}, true)
Copy the code

Abnormal Promise

Use addeventListener(‘unhandledrejection’,callback) to catch the Promise error. But you can’t capture the number of rows

window.addEventListener("unhandledrejection".(e) = > {
    console.log(e)
    let errorMsg = {
        type: 'promise'.msg: e.reason.stack || e.reason
        / /...
    }
    Axios.post({ 'https://xxxx', errorMsg })
    
    // If return true, the error is not thrown to the console
})
new Promise(() = > {
    s
})
Copy the code

This is what it printed out

Vue abnormal

errorHandle

Vue a handler for components that render errors not caught during functions and monitors. But once the error is caught by this method, the error is not thrown to the console

Vue.config.errorHandler = (err, vm, info) = > {
    // err Error handling
    // Vm vue instance
    // info is the vue specific error message, such as which lifecycle tick

    // If you want to throw an error to the console, you need to add this line here
    console.error(err)
}
Copy the code

warnHandle

Is the Vue warning to assign a custom handler. However, only in the development environment, the production environment will be self-ignored

Vue.config.warnHandle = (msg, vm, trace){
    // Trace is a component hierarchy
}
Copy the code

renderError

The default render function provides an alternative to render output when it encounters an error. This will be great in conjunction with hot reloading

new Vue({
    render (h){
        throw new Error('oops')
    },
    renderError (h, err){
        return h('per', {style: { color: red } }, err.stack)
    }
}).$mount('#app')
Copy the code

errorCaptured

Called when any derived component catches an error. It can return false to prevent error propagation. You can modify the component state in this check box. However, if there are conditional statements in the template or rendering function, when an error is caught, the conditional statements can short-circuit and enter an infinite render loop

Vue.component('ErrorBoundary', {data: () = >{... }errorCaptured(err, vm, info){
        // err Indicates an error message
        // The VM fires the faulty component instance
        // info Error capture location information
        return false}})Copy the code

The React abnormal

getDerivedStateFromError

React also has its own method for catching errors in all child components. This lifecycle is called when a descendant component throws an error. Note that this is called during the render phase, so side effects are not allowed

class ErrorBoundary extends React.Component {
    constructor(props) {
        super(props)
        this.state = { hasError: false}}static getDerivedStateFromError(error) {
        // Update state so that the next render will show the degraded UI
        return { hasError: true}}}Copy the code

componentDidCatch

This lifecycle is also called when a descendant component throws an error, but does not catch exceptions for event handlers and asynchronous code. It is called during the [commit] phase, so side effects are allowed

class ErrorBoundary extends React.Component {
    constructor(props) {
        super(props)
    } 
    componentDidCatch(error, info){
        // Error Indicates the error information
        // Info.componentStack Error component location}}Copy the code

Having said all kinds of exception handling that can happen on the front end, what about the back end? Front-end Dr Is

The front-end disaster

Front-end DISASTER recovery refers to the scenario where the back-end interface is down due to various reasons (for example, the server is powered off or the network is disconnected), but the front-end interface can still display the complete page information.

What if the banner or the list or whatever it is that’s getting the data from the interface, what if the interface can’t get it?

LocalStorage

First, use LocalStorage

When the interface returns normally, the data is saved to the LocalStorage. You can use the interface path as the key and the returned data as the value

Then the second request, as long as the request failed, read the LocalStorage, the last data out to show, and reported error information, in order to obtain the buffer time

CDN

At the same time, a copy of static data should be backed up to the CDN for each update

When the interface request fails and the LocalStorage has no data, the CDN is used to extract the backup static data

Service Worker

If you want to save not just the interface data, but the entire HTML, you can use the Service Worker for offline storage

Use the Service Worker’s request interception to store both interface data and static resource files for the page

// Intercepts all requested data in the request event cache
self.addEventListener('fetch'.e= > { 
    // Look for the response hit by the cache in the request
    e.respondWith(caches.match(e.request).then( response= > { 
        if (response) { 
            return response 
        } 
        console.log('fetch source')}})))Copy the code

Do this, and the whole site can be completely offline

conclusion

Praise support, hand stay fragrance, and have glory yan

Thank you for seeing this!